Dwarf update for readelf

readelf complained about DW_AT_stmt_list and DW_AT_location.
For dwarf >= 4 we should use DW_FORM_sec_offset instead of DW_FORM_data4
and DW_FORM_exprloc instead of DW_FORM_block1.
This is fixed in tccgen.c

I also updated tccrun.c to use dwarf_read_1 instead of DW_GETC.
This commit is contained in:
herman ten brugge 2022-05-09 08:04:37 +02:00
parent 499cf2305b
commit 0241120b54
2 changed files with 60 additions and 55 deletions

View File

@ -276,7 +276,7 @@ static const unsigned char dwarf_abbrev_init[] = {
#else
DW_AT_high_pc, DW_FORM_data8,
#endif
DW_AT_stmt_list, DW_FORM_data4,
DW_AT_stmt_list, DW_FORM_sec_offset,
0, 0,
DWARF_ABBREV_BASE_TYPE, DW_TAG_base_type, 0,
DW_AT_byte_size, DW_FORM_udata,
@ -289,24 +289,24 @@ static const unsigned char dwarf_abbrev_init[] = {
DW_AT_decl_line, DW_FORM_udata,
DW_AT_type, DW_FORM_ref4,
DW_AT_external, DW_FORM_flag,
DW_AT_location, DW_FORM_block1,
DW_AT_location, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_VARIABLE_STATIC, DW_TAG_variable, 0,
DW_AT_name, DW_FORM_strp,
DW_AT_decl_file, DW_FORM_udata,
DW_AT_decl_line, DW_FORM_udata,
DW_AT_type, DW_FORM_ref4,
DW_AT_location, DW_FORM_block1,
DW_AT_location, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_VARIABLE_LOCAL, DW_TAG_variable, 0,
DW_AT_name, DW_FORM_strp,
DW_AT_type, DW_FORM_ref4,
DW_AT_location, DW_FORM_block1,
DW_AT_location, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_FORMAL_PARAMETER, DW_TAG_formal_parameter, 0,
DW_AT_name, DW_FORM_strp,
DW_AT_type, DW_FORM_ref4,
DW_AT_location, DW_FORM_block1,
DW_AT_location, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_POINTER, DW_TAG_pointer_type, 0,
DW_AT_byte_size, DW_FORM_data1,
@ -381,7 +381,7 @@ static const unsigned char dwarf_abbrev_init[] = {
DW_AT_high_pc, DW_FORM_data8,
#endif
DW_AT_sibling, DW_FORM_ref4,
DW_AT_frame_base, DW_FORM_block1,
DW_AT_frame_base, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_SUBPROGRAM_STATIC, DW_TAG_subprogram, 1,
DW_AT_name, DW_FORM_strp,
@ -395,7 +395,7 @@ static const unsigned char dwarf_abbrev_init[] = {
DW_AT_high_pc, DW_FORM_data8,
#endif
DW_AT_sibling, DW_FORM_ref4,
DW_AT_frame_base, DW_FORM_block1,
DW_AT_frame_base, DW_FORM_exprloc,
0, 0,
DWARF_ABBREV_LEXICAL_BLOCK, DW_TAG_lexical_block, 1,
DW_AT_low_pc, DW_FORM_addr,
@ -838,7 +838,6 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
#ifdef _WIN32
normalize_slashes(buf);
#endif
pstrcat(buf, sizeof(buf), "/");
if (s1->dwarf) {
int start_abbrev;
@ -855,8 +854,19 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
while (*ptr) {
if (ptr[1] == DW_FORM_line_strp)
ptr[1] = DW_FORM_strp;
if (s1->dwarf < 4) {
/* These are compatable for DW_TAG_compile_unit
DW_AT_stmt_list. */
if (ptr[1] == DW_FORM_sec_offset)
ptr[1] = DW_FORM_data4;
/* This code uses only size < 0x80 so these are
compatible. */
if (ptr[1] == DW_FORM_exprloc)
ptr[1] = DW_FORM_block1;
}
ptr += 2;
}
ptr += 2;
}
}
@ -949,6 +959,7 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
}
else {
/* file info: full path + filename */
pstrcat(buf, sizeof(buf), "/");
section_sym = put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
text_section->sh_num, NULL);
@ -1374,7 +1385,8 @@ static void tcc_debug_fix_anon(CType *t)
debug_type = tcc_get_dwarf_info(s1, &sym);
for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
write32le(dwarf_info_section->data +
debug_anon_hash[i].debug_type[j], debug_type);
debug_anon_hash[i].debug_type[j],
debug_type - dwarf_info.start);
tcc_free(debug_anon_hash[i].debug_type);
n_debug_anon_hash--;
for (; i < n_debug_anon_hash; i++)

View File

@ -590,11 +590,28 @@ found:
#define MAX_128 ((8 * sizeof (long long) + 6) / 7)
#define DW_GETC(s,e) ((s) < (e) ? *(s)++ : 0)
#define DIR_TABLE_SIZE (64)
#define FILE_TABLE_SIZE (256)
#define dwarf_read_1(ln,end) \
((ln) < (end) ? *(ln)++ : 0)
#define dwarf_read_2(ln,end) \
((ln) + 2 < (end) ? (ln) += 2, read16le((ln) - 2) : 0)
#define dwarf_read_4(ln,end) \
((ln) + 4 < (end) ? (ln) += 4, read32le((ln) - 4) : 0)
#define dwarf_read_8(ln,end) \
((ln) + 8 < (end) ? (ln) += 8, read64le((ln) - 8) : 0)
#define dwarf_ignore_type(ln, end) /* timestamp/size/md5/... */ \
switch (entry_format[j].form) { \
case DW_FORM_data1: (ln) += 1; break; \
case DW_FORM_data2: (ln) += 2; break; \
case DW_FORM_data4: (ln) += 3; break; \
case DW_FORM_data8: (ln) += 8; break; \
case DW_FORM_data16: (ln) += 16; break; \
case DW_FORM_udata: dwarf_read_uleb128(&(ln), (end)); break; \
default: goto next_line; \
}
static unsigned long long
dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
{
@ -603,7 +620,7 @@ dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
int i;
for (i = 0; i < MAX_128; i++) {
unsigned long long byte = DW_GETC(cp, end);
unsigned long long byte = dwarf_read_1(cp, end);
retval |= (byte & 0x7f) << (i * 7);
if ((byte & 0x80) == 0)
@ -621,7 +638,7 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
int i;
for (i = 0; i < MAX_128; i++) {
unsigned long long byte = DW_GETC(cp, end);
unsigned long long byte = dwarf_read_1(cp, end);
retval |= (byte & 0x7f) << (i * 7);
if ((byte & 0x80) == 0) {
@ -634,25 +651,6 @@ dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
return retval;
}
#define dwarf_read_1(ln,end) \
DW_GETC((ln), (end))
#define dwarf_read_2(ln,end) \
((ln) + 2 < (end) ? (ln) += 2, read16le((ln) - 2) : 0)
#define dwarf_read_4(ln,end) \
((ln) + 4 < (end) ? (ln) += 4, read32le((ln) - 4) : 0)
#define dwarf_read_8(ln,end) \
((ln) + 8 < (end) ? (ln) += 8, read64le((ln) - 8) : 0)
#define dwarf_ignore_type(ln, end) /* timestamp/size/md5/... */ \
switch (entry_format[j].form) { \
case DW_FORM_data1: (ln) += 1; break; \
case DW_FORM_data2: (ln) += 2; break; \
case DW_FORM_data4: (ln) += 3; break; \
case DW_FORM_data8: (ln) += 8; break; \
case DW_FORM_data16: (ln) += 16; break; \
case DW_FORM_udata: dwarf_read_uleb128(&(ln), (end)); break; \
default: goto next_line; \
}
static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
const char *msg, const char *skip)
{
@ -706,26 +704,25 @@ next:
function = NULL;
size = dwarf_read_4(ln, rc->dwarf_line_end);
end = ln + size;
version = DW_GETC(ln, end);
version += DW_GETC(ln, end) << 8;
version = dwarf_read_2(ln, end);
if (version >= 5)
ln += 6; // address size, segment selector, prologue Length
else
ln += 4; // prologue Length
min_insn_length = DW_GETC(ln, end);
min_insn_length = dwarf_read_1(ln, end);
if (version >= 4)
max_ops_per_insn = DW_GETC(ln, end);
max_ops_per_insn = dwarf_read_1(ln, end);
else
max_ops_per_insn = 1;
ln++; // Initial value of 'is_stmt'
line_base = DW_GETC(ln, end);
line_base = dwarf_read_1(ln, end);
line_base |= line_base >= 0x80 ? ~0xff : 0;
line_range = DW_GETC(ln, end);
opcode_base = DW_GETC(ln, end);
line_range = dwarf_read_1(ln, end);
opcode_base = dwarf_read_1(ln, end);
opindex = 0;
ln += 12;
if (version >= 5) {
col = DW_GETC(ln, end);
col = dwarf_read_1(ln, end);
for (i = 0; i < col; i++) {
entry_format[i].type = dwarf_read_uleb128(&ln, end);
entry_format[i].form = dwarf_read_uleb128(&ln, end);
@ -748,7 +745,7 @@ next:
dwarf_ignore_type(ln, end);
}
}
col = DW_GETC(ln, end);
col = dwarf_read_1(ln, end);
for (i = 0; i < col; i++) {
entry_format[i].type = dwarf_read_uleb128(&ln, end);
entry_format[i].form = dwarf_read_uleb128(&ln, end);
@ -780,22 +777,22 @@ next:
}
}
else {
while ((DW_GETC(ln, end))) {
while ((dwarf_read_1(ln, end))) {
#if 0
if (++dir_size < DIR_TABLE_SIZE)
dirs[dir_size - 1] = (char *)ln - 1;
#endif
while (DW_GETC(ln, end)) {}
while (dwarf_read_1(ln, end)) {}
}
while ((DW_GETC(ln, end))) {
while ((dwarf_read_1(ln, end))) {
if (++filename_size < FILE_TABLE_SIZE) {
filename_table[filename_size - 1].name = (char *)ln - 1;
while (DW_GETC(ln, end)) {}
while (dwarf_read_1(ln, end)) {}
filename_table[filename_size - 1].dir_entry =
dwarf_read_uleb128(&ln, end);
}
else {
while (DW_GETC(ln, end)) {}
while (dwarf_read_1(ln, end)) {}
dwarf_read_uleb128(&ln, end);
}
dwarf_read_uleb128(&ln, end); // time
@ -806,14 +803,14 @@ next:
filename = filename_table[0].name;
while (ln < end) {
last_pc = pc;
switch (DW_GETC(ln, end)) {
switch (dwarf_read_1(ln, end)) {
case 0:
len = dwarf_read_uleb128(&ln, end);
cp = ln;
ln += len;
if (len == 0)
goto next_line;
switch (DW_GETC(cp, end)) {
switch (dwarf_read_1(cp, end)) {
case DW_LNE_end_sequence:
goto next_line;
case DW_LNE_set_address:
@ -829,20 +826,17 @@ next:
case DW_LNE_define_file: /* deprecated */
if (++filename_size < FILE_TABLE_SIZE) {
filename_table[filename_size - 1].name = (char *)ln - 1;
while (DW_GETC(ln, end)) {}
while (dwarf_read_1(ln, end)) {}
filename_table[filename_size - 1].dir_entry =
dwarf_read_uleb128(&ln, end);
}
else {
while (DW_GETC(ln, end)) {}
while (dwarf_read_1(ln, end)) {}
dwarf_read_uleb128(&ln, end);
}
dwarf_read_uleb128(&ln, end); // time
dwarf_read_uleb128(&ln, end); // size
break;
case DW_LNE_set_discriminator:
dwarf_read_uleb128(&cp, end);
break;
case DW_LNE_hi_user - 1:
function = (char *)cp;
func_addr = pc;
@ -893,8 +887,7 @@ next:
i = 0;
goto check_pc;
case DW_LNS_fixed_advance_pc:
i = DW_GETC(ln, end);
i += DW_GETC(ln, end) << 8;
i = dwarf_read_2(ln, end);
pc += i;
opindex = 0;
i = 0;