cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

genelf_debug.c (14372B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * genelf_debug.c
      4 * Copyright (C) 2015, Google, Inc
      5 *
      6 * Contributed by:
      7 * 	Stephane Eranian <eranian@google.com>
      8 *
      9 * based on GPLv2 source code from Oprofile
     10 * @remark Copyright 2007 OProfile authors
     11 * @author Philippe Elie
     12 */
     13#include <linux/compiler.h>
     14#include <sys/types.h>
     15#include <stdio.h>
     16#include <getopt.h>
     17#include <stddef.h>
     18#include <libelf.h>
     19#include <string.h>
     20#include <stdlib.h>
     21#include <inttypes.h>
     22#include <limits.h>
     23#include <fcntl.h>
     24#include <err.h>
     25#include <dwarf.h>
     26
     27#include "genelf.h"
     28#include "../util/jitdump.h"
     29
     30#define BUFFER_EXT_DFL_SIZE	(4 * 1024)
     31
     32typedef uint32_t uword;
     33typedef uint16_t uhalf;
     34typedef int32_t  sword;
     35typedef int16_t  shalf;
     36typedef uint8_t  ubyte;
     37typedef int8_t   sbyte;
     38
     39struct buffer_ext {
     40	size_t cur_pos;
     41	size_t max_sz;
     42	void *data;
     43};
     44
     45static void
     46buffer_ext_dump(struct buffer_ext *be, const char *msg)
     47{
     48	size_t i;
     49	warnx("DUMP for %s", msg);
     50	for (i = 0 ; i < be->cur_pos; i++)
     51		warnx("%4zu 0x%02x", i, (((char *)be->data)[i]) & 0xff);
     52}
     53
     54static inline int
     55buffer_ext_add(struct buffer_ext *be, void *addr, size_t sz)
     56{
     57	void *tmp;
     58	size_t be_sz = be->max_sz;
     59
     60retry:
     61	if ((be->cur_pos + sz) < be_sz) {
     62		memcpy(be->data + be->cur_pos, addr, sz);
     63		be->cur_pos += sz;
     64		return 0;
     65	}
     66
     67	if (!be_sz)
     68		be_sz = BUFFER_EXT_DFL_SIZE;
     69	else
     70		be_sz <<= 1;
     71
     72	tmp = realloc(be->data, be_sz);
     73	if (!tmp)
     74		return -1;
     75
     76	be->data   = tmp;
     77	be->max_sz = be_sz;
     78
     79	goto retry;
     80}
     81
     82static void
     83buffer_ext_init(struct buffer_ext *be)
     84{
     85	be->data = NULL;
     86	be->cur_pos = 0;
     87	be->max_sz = 0;
     88}
     89
     90static inline size_t
     91buffer_ext_size(struct buffer_ext *be)
     92{
     93	return be->cur_pos;
     94}
     95
     96static inline void *
     97buffer_ext_addr(struct buffer_ext *be)
     98{
     99	return be->data;
    100}
    101
    102struct debug_line_header {
    103	// Not counting this field
    104	uword total_length;
    105	// version number (2 currently)
    106	uhalf version;
    107	// relative offset from next field to
    108	// program statement
    109	uword prolog_length;
    110	ubyte minimum_instruction_length;
    111	ubyte default_is_stmt;
    112	// line_base - see DWARF 2 specs
    113	sbyte line_base;
    114	// line_range - see DWARF 2 specs
    115	ubyte line_range;
    116	// number of opcode + 1
    117	ubyte opcode_base;
    118	/* follow the array of opcode args nr: ubytes [nr_opcode_base] */
    119	/* follow the search directories index, zero terminated string
    120	 * terminated by an empty string.
    121	 */
    122	/* follow an array of { filename, LEB128, LEB128, LEB128 }, first is
    123	 * the directory index entry, 0 means current directory, then mtime
    124	 * and filesize, last entry is followed by en empty string.
    125	 */
    126	/* follow the first program statement */
    127} __packed;
    128
    129/* DWARF 2 spec talk only about one possible compilation unit header while
    130 * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not
    131 * related to the used arch, an ELF 32 can hold more than 4 Go of debug
    132 * information. For now we handle only DWARF 2 32 bits comp unit. It'll only
    133 * become a problem if we generate more than 4GB of debug information.
    134 */
    135struct compilation_unit_header {
    136	uword total_length;
    137	uhalf version;
    138	uword debug_abbrev_offset;
    139	ubyte pointer_size;
    140} __packed;
    141
    142#define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
    143
    144/* field filled at run time are marked with -1 */
    145static struct debug_line_header const default_debug_line_header = {
    146	.total_length = -1,
    147	.version = 2,
    148	.prolog_length = -1,
    149	.minimum_instruction_length = 1,	/* could be better when min instruction size != 1 */
    150	.default_is_stmt = 1,	/* we don't take care about basic block */
    151	.line_base = -5,	/* sensible value for line base ... */
    152	.line_range = -14,     /* ... and line range are guessed statically */
    153	.opcode_base = DW_LNS_num_opcode
    154};
    155
    156static ubyte standard_opcode_length[] =
    157{
    158	0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1
    159};
    160#if 0
    161{
    162	[DW_LNS_advance_pc]   = 1,
    163	[DW_LNS_advance_line] = 1,
    164	[DW_LNS_set_file] =  1,
    165	[DW_LNS_set_column] = 1,
    166	[DW_LNS_fixed_advance_pc] = 1,
    167	[DW_LNS_set_isa] = 1,
    168};
    169#endif
    170
    171/* field filled at run time are marked with -1 */
    172static struct compilation_unit_header default_comp_unit_header = {
    173	.total_length = -1,
    174	.version = 2,
    175	.debug_abbrev_offset = 0,     /* we reuse the same abbrev entries for all comp unit */
    176	.pointer_size = sizeof(void *)
    177};
    178
    179static void emit_uword(struct buffer_ext *be, uword data)
    180{
    181	buffer_ext_add(be, &data, sizeof(uword));
    182}
    183
    184static void emit_string(struct buffer_ext *be, const char *s)
    185{
    186	buffer_ext_add(be, (void *)s, strlen(s) + 1);
    187}
    188
    189static void emit_unsigned_LEB128(struct buffer_ext *be,
    190				 unsigned long data)
    191{
    192	do {
    193		ubyte cur = data & 0x7F;
    194		data >>= 7;
    195		if (data)
    196			cur |= 0x80;
    197		buffer_ext_add(be, &cur, 1);
    198	} while (data);
    199}
    200
    201static void emit_signed_LEB128(struct buffer_ext *be, long data)
    202{
    203	int more = 1;
    204	int negative = data < 0;
    205	int size = sizeof(long) * CHAR_BIT;
    206	while (more) {
    207		ubyte cur = data & 0x7F;
    208		data >>= 7;
    209		if (negative)
    210			data |= - (1 << (size - 7));
    211		if ((data == 0 && !(cur & 0x40)) ||
    212		    (data == -1l && (cur & 0x40)))
    213			more = 0;
    214		else
    215			cur |= 0x80;
    216		buffer_ext_add(be, &cur, 1);
    217	}
    218}
    219
    220static void emit_extended_opcode(struct buffer_ext *be, ubyte opcode,
    221				 void *data, size_t data_len)
    222{
    223	buffer_ext_add(be, (char *)"", 1);
    224
    225	emit_unsigned_LEB128(be, data_len + 1);
    226
    227	buffer_ext_add(be, &opcode, 1);
    228	buffer_ext_add(be, data, data_len);
    229}
    230
    231static void emit_opcode(struct buffer_ext *be, ubyte opcode)
    232{
    233	buffer_ext_add(be, &opcode, 1);
    234}
    235
    236static void emit_opcode_signed(struct buffer_ext  *be,
    237			       ubyte opcode, long data)
    238{
    239	buffer_ext_add(be, &opcode, 1);
    240	emit_signed_LEB128(be, data);
    241}
    242
    243static void emit_opcode_unsigned(struct buffer_ext *be, ubyte opcode,
    244				 unsigned long data)
    245{
    246	buffer_ext_add(be, &opcode, 1);
    247	emit_unsigned_LEB128(be, data);
    248}
    249
    250static void emit_advance_pc(struct buffer_ext *be, unsigned long delta_pc)
    251{
    252	emit_opcode_unsigned(be, DW_LNS_advance_pc, delta_pc);
    253}
    254
    255static void emit_advance_lineno(struct buffer_ext  *be, long delta_lineno)
    256{
    257	emit_opcode_signed(be, DW_LNS_advance_line, delta_lineno);
    258}
    259
    260static void emit_lne_end_of_sequence(struct buffer_ext *be)
    261{
    262	emit_extended_opcode(be, DW_LNE_end_sequence, NULL, 0);
    263}
    264
    265static void emit_set_file(struct buffer_ext *be, unsigned long idx)
    266{
    267	emit_opcode_unsigned(be, DW_LNS_set_file, idx);
    268}
    269
    270static void emit_lne_define_filename(struct buffer_ext *be,
    271				     const char *filename)
    272{
    273	buffer_ext_add(be, (void *)"", 1);
    274
    275	/* LNE field, strlen(filename) + zero termination, 3 bytes for: the dir entry, timestamp, filesize */
    276	emit_unsigned_LEB128(be, strlen(filename) + 5);
    277	emit_opcode(be, DW_LNE_define_file);
    278	emit_string(be, filename);
    279	/* directory index 0=do not know */
    280        emit_unsigned_LEB128(be, 0);
    281	/* last modification date on file 0=do not know */
    282        emit_unsigned_LEB128(be, 0);
    283	/* filesize 0=do not know */
    284        emit_unsigned_LEB128(be, 0);
    285}
    286
    287static void emit_lne_set_address(struct buffer_ext *be,
    288				 void *address)
    289{
    290	emit_extended_opcode(be, DW_LNE_set_address, &address, sizeof(unsigned long));
    291}
    292
    293static ubyte get_special_opcode(struct debug_entry *ent,
    294				unsigned int last_line,
    295				unsigned long last_vma)
    296{
    297	unsigned int temp;
    298	unsigned long delta_addr;
    299
    300	/*
    301	 * delta from line_base
    302	 */
    303	temp = (ent->lineno - last_line) - default_debug_line_header.line_base;
    304
    305	if (temp >= default_debug_line_header.line_range)
    306		return 0;
    307
    308	/*
    309	 * delta of addresses
    310	 */
    311	delta_addr = (ent->addr - last_vma) / default_debug_line_header.minimum_instruction_length;
    312
    313	/* This is not sufficient to ensure opcode will be in [0-256] but
    314	 * sufficient to ensure when summing with the delta lineno we will
    315	 * not overflow the unsigned long opcode */
    316
    317	if (delta_addr <= 256 / default_debug_line_header.line_range) {
    318		unsigned long opcode = temp +
    319			(delta_addr * default_debug_line_header.line_range) +
    320			default_debug_line_header.opcode_base;
    321
    322		return opcode <= 255 ? opcode : 0;
    323	}
    324	return 0;
    325}
    326
    327static void emit_lineno_info(struct buffer_ext *be,
    328			     struct debug_entry *ent, size_t nr_entry,
    329			     unsigned long code_addr)
    330{
    331	size_t i;
    332
    333	/*
    334	 * Machine state at start of a statement program
    335	 * address = 0
    336	 * file    = 1
    337	 * line    = 1
    338	 * column  = 0
    339	 * is_stmt = default_is_stmt as given in the debug_line_header
    340	 * basic block = 0
    341	 * end sequence = 0
    342	 */
    343
    344	/* start state of the state machine we take care of */
    345	unsigned long last_vma = 0;
    346	char const  *cur_filename = NULL;
    347	unsigned long cur_file_idx = 0;
    348	int last_line = 1;
    349
    350	emit_lne_set_address(be, (void *)code_addr);
    351
    352	for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) {
    353		int need_copy = 0;
    354		ubyte special_opcode;
    355
    356		/*
    357		 * check if filename changed, if so add it
    358		 */
    359		if (!cur_filename || strcmp(cur_filename, ent->name)) {
    360			emit_lne_define_filename(be, ent->name);
    361			cur_filename = ent->name;
    362			emit_set_file(be, ++cur_file_idx);
    363			need_copy = 1;
    364		}
    365
    366		special_opcode = get_special_opcode(ent, last_line, last_vma);
    367		if (special_opcode != 0) {
    368			last_line = ent->lineno;
    369			last_vma  = ent->addr;
    370			emit_opcode(be, special_opcode);
    371		} else {
    372			/*
    373			 * lines differ, emit line delta
    374			 */
    375			if (last_line != ent->lineno) {
    376				emit_advance_lineno(be, ent->lineno - last_line);
    377				last_line = ent->lineno;
    378				need_copy = 1;
    379			}
    380			/*
    381			 * addresses differ, emit address delta
    382			 */
    383			if (last_vma != ent->addr) {
    384				emit_advance_pc(be, ent->addr - last_vma);
    385				last_vma = ent->addr;
    386				need_copy = 1;
    387			}
    388			/*
    389			 * add new row to matrix
    390			 */
    391			if (need_copy)
    392				emit_opcode(be, DW_LNS_copy);
    393		}
    394	}
    395}
    396
    397static void add_debug_line(struct buffer_ext *be,
    398	struct debug_entry *ent, size_t nr_entry,
    399	unsigned long code_addr)
    400{
    401	struct debug_line_header * dbg_header;
    402	size_t old_size;
    403
    404	old_size = buffer_ext_size(be);
    405
    406	buffer_ext_add(be, (void *)&default_debug_line_header,
    407		 sizeof(default_debug_line_header));
    408
    409	buffer_ext_add(be, &standard_opcode_length,  sizeof(standard_opcode_length));
    410
    411	// empty directory entry
    412	buffer_ext_add(be, (void *)"", 1);
    413
    414	// empty filename directory
    415	buffer_ext_add(be, (void *)"", 1);
    416
    417	dbg_header = buffer_ext_addr(be) + old_size;
    418	dbg_header->prolog_length = (buffer_ext_size(be) - old_size) -
    419		offsetof(struct debug_line_header, minimum_instruction_length);
    420
    421	emit_lineno_info(be, ent, nr_entry, code_addr);
    422
    423	emit_lne_end_of_sequence(be);
    424
    425	dbg_header = buffer_ext_addr(be) + old_size;
    426	dbg_header->total_length = (buffer_ext_size(be) - old_size) -
    427		offsetof(struct debug_line_header, version);
    428}
    429
    430static void
    431add_debug_abbrev(struct buffer_ext *be)
    432{
    433        emit_unsigned_LEB128(be, 1);
    434        emit_unsigned_LEB128(be, DW_TAG_compile_unit);
    435        emit_unsigned_LEB128(be, DW_CHILDREN_yes);
    436        emit_unsigned_LEB128(be, DW_AT_stmt_list);
    437        emit_unsigned_LEB128(be, DW_FORM_data4);
    438        emit_unsigned_LEB128(be, 0);
    439        emit_unsigned_LEB128(be, 0);
    440        emit_unsigned_LEB128(be, 0);
    441}
    442
    443static void
    444add_compilation_unit(struct buffer_ext *be,
    445		     size_t offset_debug_line)
    446{
    447	struct compilation_unit_header *comp_unit_header;
    448	size_t old_size = buffer_ext_size(be);
    449
    450	buffer_ext_add(be, &default_comp_unit_header,
    451		       sizeof(default_comp_unit_header));
    452
    453	emit_unsigned_LEB128(be, 1);
    454	emit_uword(be, offset_debug_line);
    455
    456	comp_unit_header = buffer_ext_addr(be) + old_size;
    457	comp_unit_header->total_length = (buffer_ext_size(be) - old_size) -
    458		offsetof(struct compilation_unit_header, version);
    459}
    460
    461static int
    462jit_process_debug_info(uint64_t code_addr,
    463		       void *debug, int nr_debug_entries,
    464		       struct buffer_ext *dl,
    465		       struct buffer_ext *da,
    466		       struct buffer_ext *di)
    467{
    468	struct debug_entry *ent = debug;
    469	int i;
    470
    471	for (i = 0; i < nr_debug_entries; i++) {
    472		ent->addr = ent->addr - code_addr;
    473		ent = debug_entry_next(ent);
    474	}
    475	add_compilation_unit(di, buffer_ext_size(dl));
    476	add_debug_line(dl, debug, nr_debug_entries, GEN_ELF_TEXT_OFFSET);
    477	add_debug_abbrev(da);
    478	if (0) buffer_ext_dump(da, "abbrev");
    479
    480	return 0;
    481}
    482
    483int
    484jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries)
    485{
    486	Elf_Data *d;
    487	Elf_Scn *scn;
    488	Elf_Shdr *shdr;
    489	struct buffer_ext dl, di, da;
    490	int ret;
    491
    492	buffer_ext_init(&dl);
    493	buffer_ext_init(&di);
    494	buffer_ext_init(&da);
    495
    496	ret = jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di);
    497	if (ret)
    498		return -1;
    499	/*
    500	 * setup .debug_line section
    501	 */
    502	scn = elf_newscn(e);
    503	if (!scn) {
    504		warnx("cannot create section");
    505		return -1;
    506	}
    507
    508	d = elf_newdata(scn);
    509	if (!d) {
    510		warnx("cannot get new data");
    511		return -1;
    512	}
    513
    514	d->d_align = 1;
    515	d->d_off = 0LL;
    516	d->d_buf = buffer_ext_addr(&dl);
    517	d->d_type = ELF_T_BYTE;
    518	d->d_size = buffer_ext_size(&dl);
    519	d->d_version = EV_CURRENT;
    520
    521	shdr = elf_getshdr(scn);
    522	if (!shdr) {
    523		warnx("cannot get section header");
    524		return -1;
    525	}
    526
    527	shdr->sh_name = 52; /* .debug_line */
    528	shdr->sh_type = SHT_PROGBITS;
    529	shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
    530	shdr->sh_flags = 0;
    531	shdr->sh_entsize = 0;
    532
    533	/*
    534	 * setup .debug_info section
    535	 */
    536	scn = elf_newscn(e);
    537	if (!scn) {
    538		warnx("cannot create section");
    539		return -1;
    540	}
    541
    542	d = elf_newdata(scn);
    543	if (!d) {
    544		warnx("cannot get new data");
    545		return -1;
    546	}
    547
    548	d->d_align = 1;
    549	d->d_off = 0LL;
    550	d->d_buf = buffer_ext_addr(&di);
    551	d->d_type = ELF_T_BYTE;
    552	d->d_size = buffer_ext_size(&di);
    553	d->d_version = EV_CURRENT;
    554
    555	shdr = elf_getshdr(scn);
    556	if (!shdr) {
    557		warnx("cannot get section header");
    558		return -1;
    559	}
    560
    561	shdr->sh_name = 64; /* .debug_info */
    562	shdr->sh_type = SHT_PROGBITS;
    563	shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
    564	shdr->sh_flags = 0;
    565	shdr->sh_entsize = 0;
    566
    567	/*
    568	 * setup .debug_abbrev section
    569	 */
    570	scn = elf_newscn(e);
    571	if (!scn) {
    572		warnx("cannot create section");
    573		return -1;
    574	}
    575
    576	d = elf_newdata(scn);
    577	if (!d) {
    578		warnx("cannot get new data");
    579		return -1;
    580	}
    581
    582	d->d_align = 1;
    583	d->d_off = 0LL;
    584	d->d_buf = buffer_ext_addr(&da);
    585	d->d_type = ELF_T_BYTE;
    586	d->d_size = buffer_ext_size(&da);
    587	d->d_version = EV_CURRENT;
    588
    589	shdr = elf_getshdr(scn);
    590	if (!shdr) {
    591		warnx("cannot get section header");
    592		return -1;
    593	}
    594
    595	shdr->sh_name = 76; /* .debug_info */
    596	shdr->sh_type = SHT_PROGBITS;
    597	shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
    598	shdr->sh_flags = 0;
    599	shdr->sh_entsize = 0;
    600
    601	/*
    602	 * now we update the ELF image with all the sections
    603	 */
    604	if (elf_update(e, ELF_C_WRITE) < 0) {
    605		warnx("elf_update debug failed");
    606		return -1;
    607	}
    608	return 0;
    609}