struct debug_line_header { // Not counting this field
uword total_length; // version number (2 currently)
uhalf version; // relative offset from next field to // program statement
uword prolog_length;
ubyte minimum_instruction_length;
ubyte default_is_stmt; // line_base - see DWARF 2 specs
sbyte line_base; // line_range - see DWARF 2 specs
ubyte line_range; // number of opcode + 1
ubyte opcode_base; /* follow the array of opcode args nr: ubytes [nr_opcode_base] */ /* follow the search directories index, zero terminated string * terminated by an empty string.
*/ /* follow an array of { filename, LEB128, LEB128, LEB128 }, first is * the directory index entry, 0 means current directory, then mtime * and filesize, last entry is followed by en empty string.
*/ /* follow the first program statement */
} __packed;
/* DWARF 2 spec talk only about one possible compilation unit header while * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not * related to the used arch, an ELF 32 can hold more than 4 Go of debug * information. For now we handle only DWARF 2 32 bits comp unit. It'll only * become a problem if we generate more than 4GB of debug information.
*/ struct compilation_unit_header {
uword total_length;
uhalf version;
uword debug_abbrev_offset;
ubyte pointer_size;
} __packed;
#define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
/* field filled at run time are marked with -1 */ staticstruct debug_line_header const default_debug_line_header = {
.total_length = -1,
.version = 2,
.prolog_length = -1,
.minimum_instruction_length = 1, /* could be better when min instruction size != 1 */
.default_is_stmt = 1, /* we don't take care about basic block */
.line_base = -5, /* sensible value for line base ... */
.line_range = -14, /* ... and line range are guessed statically */
.opcode_base = DW_LNS_num_opcode
};
/* field filled at run time are marked with -1 */ staticstruct compilation_unit_header default_comp_unit_header = {
.total_length = -1,
.version = 2,
.debug_abbrev_offset = 0, /* we reuse the same abbrev entries for all comp unit */
.pointer_size = sizeof(void *)
};
staticvoid emit_unsigned_LEB128(struct buffer_ext *be, unsignedlong data)
{ do {
ubyte cur = data & 0x7F;
data >>= 7; if (data)
cur |= 0x80;
buffer_ext_add(be, &cur, 1);
} while (data);
}
staticvoid emit_signed_LEB128(struct buffer_ext *be, long data)
{ int more = 1; int negative = data < 0; int size = sizeof(long) * CHAR_BIT; while (more) {
ubyte cur = data & 0x7F;
data >>= 7; if (negative)
data |= - (1 << (size - 7)); if ((data == 0 && !(cur & 0x40)) ||
(data == -1l && (cur & 0x40)))
more = 0; else
cur |= 0x80;
buffer_ext_add(be, &cur, 1);
}
}
/* This is not sufficient to ensure opcode will be in [0-256] but * sufficient to ensure when summing with the delta lineno we will
* not overflow the unsigned long opcode */
/* as described in the jitdump format */ constchar repeated_name_marker[] = {'\xff', '\0'};
/* * Machine state at start of a statement program * address = 0 * file = 1 * line = 1 * column = 0 * is_stmt = default_is_stmt as given in the debug_line_header * basic block = 0 * end sequence = 0
*/
/* start state of the state machine we take care of */ unsignedlong last_vma = 0; charconst *cur_filename = NULL; unsignedlong cur_file_idx = 0; int last_line = 1;
emit_lne_set_address(be, (void *)code_addr);
for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) { int need_copy = 0;
ubyte special_opcode;
/* * check if filename changed, if so add it
*/ if ((!cur_filename || strcmp(cur_filename, ent->name)) &&
strcmp(repeated_name_marker, ent->name)) {
emit_lne_define_filename(be, ent->name);
cur_filename = ent->name;
emit_set_file(be, ++cur_file_idx);
need_copy = 1;
}
for (i = 0; i < nr_debug_entries; i++) {
ent->addr = ent->addr - code_addr;
ent = debug_entry_next(ent);
}
add_compilation_unit(di, buffer_ext_size(dl));
add_debug_line(dl, debug, nr_debug_entries, GEN_ELF_TEXT_OFFSET);
add_debug_abbrev(da); if (0) buffer_ext_dump(da, "abbrev");
return 0;
}
int
jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries)
{
Elf_Data *d;
Elf_Scn *scn;
Elf_Shdr *shdr; struct buffer_ext dl, di, da; int ret = -1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.