mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-08 08:40:08 +08:00
Add debug support to macos
lldb now works with this push. In tccmacho.c add S_ATTR_DEBUG to all debug sections. Add __DWARF section and rearange struct skinfo. In tccdbg.c The first filename in dwarf_line can not be used. Also had to fix structure/union/lexical_block/subroutine to allow empty childs. dwarfdump --verify complained about this.
This commit is contained in:
parent
ac0604a4d4
commit
62096265ed
104
tccdbg.c
104
tccdbg.c
@ -111,12 +111,16 @@ static const struct {
|
||||
#define DWARF_ABBREV_MEMBER 14
|
||||
#define DWARF_ABBREV_MEMBER_BF 15
|
||||
#define DWARF_ABBREV_STRUCTURE_TYPE 16
|
||||
#define DWARF_ABBREV_UNION_TYPE 17
|
||||
#define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 18
|
||||
#define DWARF_ABBREV_SUBPROGRAM_STATIC 19
|
||||
#define DWARF_ABBREV_LEXICAL_BLOCK 20
|
||||
#define DWARF_ABBREV_SUBROUTINE_TYPE 21
|
||||
#define DWARF_ABBREV_FORMAL_PARAMETER2 22
|
||||
#define DWARF_ABBREV_STRUCTURE_EMPTY_TYPE 17
|
||||
#define DWARF_ABBREV_UNION_TYPE 18
|
||||
#define DWARF_ABBREV_UNION_EMPTY_TYPE 19
|
||||
#define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 20
|
||||
#define DWARF_ABBREV_SUBPROGRAM_STATIC 21
|
||||
#define DWARF_ABBREV_LEXICAL_BLOCK 22
|
||||
#define DWARF_ABBREV_LEXICAL_EMPTY_BLOCK 23
|
||||
#define DWARF_ABBREV_SUBROUTINE_TYPE 24
|
||||
#define DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE 25
|
||||
#define DWARF_ABBREV_FORMAL_PARAMETER2 26
|
||||
|
||||
/* all entries should have been generated with dwarf_uleb128 except
|
||||
has_children. All values are currently below 128 so this currently
|
||||
@ -222,6 +226,12 @@ static const unsigned char dwarf_abbrev_init[] = {
|
||||
DW_AT_decl_line, DW_FORM_udata,
|
||||
DW_AT_sibling, DW_FORM_ref4,
|
||||
0, 0,
|
||||
DWARF_ABBREV_STRUCTURE_EMPTY_TYPE, DW_TAG_structure_type, 0,
|
||||
DW_AT_name, DW_FORM_strp,
|
||||
DW_AT_byte_size, DW_FORM_udata,
|
||||
DW_AT_decl_file, DW_FORM_udata,
|
||||
DW_AT_decl_line, DW_FORM_udata,
|
||||
0, 0,
|
||||
DWARF_ABBREV_UNION_TYPE, DW_TAG_union_type, 1,
|
||||
DW_AT_name, DW_FORM_strp,
|
||||
DW_AT_byte_size, DW_FORM_udata,
|
||||
@ -229,6 +239,12 @@ static const unsigned char dwarf_abbrev_init[] = {
|
||||
DW_AT_decl_line, DW_FORM_udata,
|
||||
DW_AT_sibling, DW_FORM_ref4,
|
||||
0, 0,
|
||||
DWARF_ABBREV_UNION_EMPTY_TYPE, DW_TAG_union_type, 0,
|
||||
DW_AT_name, DW_FORM_strp,
|
||||
DW_AT_byte_size, DW_FORM_udata,
|
||||
DW_AT_decl_file, DW_FORM_udata,
|
||||
DW_AT_decl_line, DW_FORM_udata,
|
||||
0, 0,
|
||||
DWARF_ABBREV_SUBPROGRAM_EXTERNAL, DW_TAG_subprogram, 1,
|
||||
DW_AT_external, DW_FORM_flag,
|
||||
DW_AT_name, DW_FORM_strp,
|
||||
@ -264,12 +280,23 @@ static const unsigned char dwarf_abbrev_init[] = {
|
||||
DW_AT_high_pc, DW_FORM_data4,
|
||||
#else
|
||||
DW_AT_high_pc, DW_FORM_data8,
|
||||
#endif
|
||||
0, 0,
|
||||
DWARF_ABBREV_LEXICAL_EMPTY_BLOCK, DW_TAG_lexical_block, 0,
|
||||
DW_AT_low_pc, DW_FORM_addr,
|
||||
#if PTR_SIZE == 4
|
||||
DW_AT_high_pc, DW_FORM_data4,
|
||||
#else
|
||||
DW_AT_high_pc, DW_FORM_data8,
|
||||
#endif
|
||||
0, 0,
|
||||
DWARF_ABBREV_SUBROUTINE_TYPE, DW_TAG_subroutine_type, 1,
|
||||
DW_AT_type, DW_FORM_ref4,
|
||||
DW_AT_sibling, DW_FORM_ref4,
|
||||
0, 0,
|
||||
DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE, DW_TAG_subroutine_type, 0,
|
||||
DW_AT_type, DW_FORM_ref4,
|
||||
0, 0,
|
||||
DWARF_ABBREV_FORMAL_PARAMETER2, DW_TAG_formal_parameter, 0,
|
||||
DW_AT_type, DW_FORM_ref4,
|
||||
0, 0,
|
||||
@ -546,7 +573,7 @@ static void dwarf_file(TCCState *s1)
|
||||
|
||||
filename = strrchr(file->filename, '/');
|
||||
if (filename == NULL) {
|
||||
for (i = 0; i < dwarf_line.filename_size; i++)
|
||||
for (i = 1; i < dwarf_line.filename_size; i++)
|
||||
if (dwarf_line.filename_table[i].dir_entry == 0 &&
|
||||
strcmp(dwarf_line.filename_table[i].name,
|
||||
file->filename) == 0) {
|
||||
@ -789,11 +816,9 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
|
||||
tcc_malloc(2*sizeof (struct dwarf_filename_struct));
|
||||
dwarf_line.filename_table[0].dir_entry = 0;
|
||||
if (undo) {
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(undo + 1);
|
||||
dwarf_line.filename_table[1].dir_entry = 1;
|
||||
dwarf_line.filename_table[1].name = tcc_strdup(undo + 1);
|
||||
*undo = '/';
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
}
|
||||
else {
|
||||
dwarf_line.filename_table[0].name = tcc_strdup(filename);
|
||||
@ -849,17 +874,14 @@ ST_FUNC void tcc_debug_end(TCCState *s1)
|
||||
int pos = dwarf_info_section->data_offset;
|
||||
|
||||
dwarf_data1(dwarf_info_section,
|
||||
IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_TYPE
|
||||
: DWARF_ABBREV_STRUCTURE_TYPE);
|
||||
IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_EMPTY_TYPE
|
||||
: DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
|
||||
dwarf_strp(dwarf_info_section,
|
||||
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
||||
? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
|
||||
dwarf_uleb128(dwarf_info_section, 0);
|
||||
dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
|
||||
dwarf_uleb128(dwarf_info_section, file->line_num);
|
||||
j = dwarf_info_section->data_offset + 5 - dwarf_info.start;
|
||||
dwarf_data4(dwarf_info_section, j);
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
|
||||
write32le(dwarf_info_section->data +
|
||||
debug_anon_hash[i].debug_type[j],
|
||||
@ -1032,7 +1054,7 @@ ST_FUNC void tcc_debug_bincl(TCCState *s1)
|
||||
*undo = '/';
|
||||
}
|
||||
if (strcmp(filename, "<command line>")) {
|
||||
for (j = 0; j < dwarf_line.filename_size; j++)
|
||||
for (j = 1; j < dwarf_line.filename_size; j++)
|
||||
if (dwarf_line.filename_table[j].dir_entry == i &&
|
||||
strcmp (dwarf_line.filename_table[j].name, filename) == 0)
|
||||
break;
|
||||
@ -1417,7 +1439,7 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
t = t->type.ref;
|
||||
debug_type = tcc_debug_find(s1, t, 1);
|
||||
if (debug_type == -1) {
|
||||
int pos_sib, i, *pos_type;
|
||||
int pos_sib = 0, i, *pos_type;
|
||||
|
||||
debug_type = tcc_debug_add(s1, t, 1);
|
||||
e = t;
|
||||
@ -1428,16 +1450,21 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
}
|
||||
pos_type = (int *) tcc_malloc(i * sizeof(int));
|
||||
dwarf_data1(dwarf_info_section,
|
||||
IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_TYPE
|
||||
: DWARF_ABBREV_STRUCTURE_TYPE);
|
||||
IS_UNION (t->type.t)
|
||||
? t->next ? DWARF_ABBREV_UNION_TYPE
|
||||
: DWARF_ABBREV_UNION_EMPTY_TYPE
|
||||
: t->next ? DWARF_ABBREV_STRUCTURE_TYPE
|
||||
: DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
|
||||
dwarf_strp(dwarf_info_section,
|
||||
(t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
|
||||
? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
|
||||
dwarf_uleb128(dwarf_info_section, t->c);
|
||||
dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
|
||||
dwarf_uleb128(dwarf_info_section, file->line_num);
|
||||
pos_sib = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
if (t->next) {
|
||||
pos_sib = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
}
|
||||
e = t;
|
||||
i = 0;
|
||||
while (e->next) {
|
||||
@ -1462,9 +1489,11 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
else
|
||||
dwarf_uleb128(dwarf_info_section, e->c);
|
||||
}
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
write32le(dwarf_info_section->data + pos_sib,
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
if (t->next) {
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
write32le(dwarf_info_section->data + pos_sib,
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
}
|
||||
e = t;
|
||||
i = 0;
|
||||
while (e->next) {
|
||||
@ -1602,14 +1631,16 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
}
|
||||
else if (type == VT_FUNC) {
|
||||
int sib_pos, *pos_type;
|
||||
int sib_pos = 0, *pos_type;
|
||||
Sym *f;
|
||||
|
||||
i = dwarf_info_section->data_offset;
|
||||
debug_type = tcc_get_dwarf_info(s1, t->type.ref);
|
||||
if (retval == debug_type)
|
||||
retval = i;
|
||||
dwarf_data1(dwarf_info_section, DWARF_ABBREV_SUBROUTINE_TYPE);
|
||||
dwarf_data1(dwarf_info_section,
|
||||
t->type.ref->next ? DWARF_ABBREV_SUBROUTINE_TYPE
|
||||
: DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE);
|
||||
if (last_pos != -1) {
|
||||
tcc_debug_check_anon(s1, e, last_pos);
|
||||
write32le(dwarf_info_section->data + last_pos,
|
||||
@ -1618,8 +1649,10 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
last_pos = dwarf_info_section->data_offset;
|
||||
e = t->type.ref;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
sib_pos = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
if (t->type.ref->next) {
|
||||
sib_pos = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
}
|
||||
f = t->type.ref;
|
||||
i = 0;
|
||||
while (f->next) {
|
||||
@ -1635,9 +1668,11 @@ static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
|
||||
pos_type[i++] = dwarf_info_section->data_offset;
|
||||
dwarf_data4(dwarf_info_section, 0);
|
||||
}
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
write32le(dwarf_info_section->data + sib_pos,
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
if (t->type.ref->next) {
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
write32le(dwarf_info_section->data + sib_pos,
|
||||
dwarf_info_section->data_offset - dwarf_info.start);
|
||||
}
|
||||
f = t->type.ref;
|
||||
i = 0;
|
||||
while (f->next) {
|
||||
@ -1710,7 +1745,9 @@ static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur)
|
||||
tcc_free (s->str);
|
||||
}
|
||||
tcc_free (cur->sym);
|
||||
dwarf_data1(dwarf_info_section, DWARF_ABBREV_LEXICAL_BLOCK);
|
||||
dwarf_data1(dwarf_info_section,
|
||||
cur->child ? DWARF_ABBREV_LEXICAL_BLOCK
|
||||
: DWARF_ABBREV_LEXICAL_EMPTY_BLOCK);
|
||||
dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
|
||||
#if PTR_SIZE == 4
|
||||
dwarf_data4(dwarf_info_section, func_ind + cur->start);
|
||||
@ -1720,7 +1757,8 @@ static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur)
|
||||
dwarf_data8(dwarf_info_section, cur->end - cur->start);
|
||||
#endif
|
||||
tcc_debug_finish (s1, cur->child);
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
if (cur->child)
|
||||
dwarf_data1(dwarf_info_section, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
60
tccmacho.c
60
tccmacho.c
@ -228,6 +228,8 @@ struct dyld_chained_ptr_64_bind
|
||||
|
||||
#define S_ATTR_PURE_INSTRUCTIONS 0x80000000
|
||||
#define S_ATTR_SOME_INSTRUCTIONS 0x00000400
|
||||
#define S_ATTR_DEBUG 0x02000000
|
||||
|
||||
|
||||
typedef uint32_t lc_str;
|
||||
|
||||
@ -372,18 +374,18 @@ enum skind {
|
||||
sk_ro_data,
|
||||
sk_uw_info,
|
||||
sk_nl_ptr, // non-lazy pointers, aka GOT
|
||||
sk_la_ptr, // lazy pointers
|
||||
sk_init,
|
||||
sk_fini,
|
||||
sk_rw_data,
|
||||
sk_stab,
|
||||
sk_stab_str,
|
||||
sk_debug_info,
|
||||
sk_debug_abbrev,
|
||||
sk_debug_line,
|
||||
sk_debug_aranges,
|
||||
sk_debug_str,
|
||||
sk_debug_line_str,
|
||||
sk_stab,
|
||||
sk_stab_str,
|
||||
sk_la_ptr, // lazy pointers
|
||||
sk_init,
|
||||
sk_fini,
|
||||
sk_rw_data,
|
||||
sk_bss,
|
||||
sk_linkedit,
|
||||
sk_last
|
||||
@ -407,7 +409,7 @@ struct nlist_64 {
|
||||
|
||||
struct macho {
|
||||
struct mach_header_64 mh;
|
||||
int seg2lc[5], nseg;
|
||||
int seg2lc[6], nseg;
|
||||
struct load_command **lc;
|
||||
struct entry_point_command *ep;
|
||||
int nlc;
|
||||
@ -1202,20 +1204,20 @@ const struct {
|
||||
/*[sk_ro_data] =*/ { 2, S_REGULAR, "__rodata" },
|
||||
/*[sk_uw_info] =*/ { 0 },
|
||||
/*[sk_nl_ptr] =*/ { 2, S_NON_LAZY_SYMBOL_POINTERS, "__got" },
|
||||
/*[sk_la_ptr] =*/ { 3, S_LAZY_SYMBOL_POINTERS, "__la_symbol_ptr" },
|
||||
/*[sk_init] =*/ { 3, S_MOD_INIT_FUNC_POINTERS, "__mod_init_func" },
|
||||
/*[sk_fini] =*/ { 3, S_MOD_TERM_FUNC_POINTERS, "__mod_term_func" },
|
||||
/*[sk_rw_data] =*/ { 3, S_REGULAR, "__data" },
|
||||
/*[sk_stab] =*/ { 3, S_REGULAR, "__stab" },
|
||||
/*[sk_stab_str] =*/ { 3, S_REGULAR, "__stab_str" },
|
||||
/*[sk_debug_info] =*/ { 3, S_REGULAR, "__debug_info" },
|
||||
/*[sk_debug_abbrev] =*/ { 3, S_REGULAR, "__debug_abbrev" },
|
||||
/*[sk_debug_line] =*/ { 3, S_REGULAR, "__debug_line" },
|
||||
/*[sk_debug_aranges] =*/ { 3, S_REGULAR, "__debug_aranges" },
|
||||
/*[sk_debug_str] =*/ { 3, S_REGULAR, "__debug_str" },
|
||||
/*[sk_debug_line_str] =*/ { 3, S_REGULAR, "__debug_line_str" },
|
||||
/*[sk_bss] =*/ { 3, S_ZEROFILL, "__bss" },
|
||||
/*[sk_linkedit] =*/ { 4, S_REGULAR, NULL },
|
||||
/*[sk_debug_info] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_info" },
|
||||
/*[sk_debug_abbrev] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_abbrev" },
|
||||
/*[sk_debug_line] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line" },
|
||||
/*[sk_debug_aranges] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_aranges" },
|
||||
/*[sk_debug_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_str" },
|
||||
/*[sk_debug_line_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line_str" },
|
||||
/*[sk_stab] =*/ { 4, S_REGULAR, "__stab" },
|
||||
/*[sk_stab_str] =*/ { 4, S_REGULAR, "__stab_str" },
|
||||
/*[sk_la_ptr] =*/ { 4, S_LAZY_SYMBOL_POINTERS, "__la_symbol_ptr" },
|
||||
/*[sk_init] =*/ { 4, S_MOD_INIT_FUNC_POINTERS, "__mod_init_func" },
|
||||
/*[sk_fini] =*/ { 4, S_MOD_TERM_FUNC_POINTERS, "__mod_term_func" },
|
||||
/*[sk_rw_data] =*/ { 4, S_REGULAR, "__data" },
|
||||
/*[sk_bss] =*/ { 4, S_ZEROFILL, "__bss" },
|
||||
/*[sk_linkedit] =*/ { 5, S_REGULAR, NULL },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NEW_MACHO
|
||||
@ -1285,7 +1287,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
||||
*ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
|
||||
(BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
|
||||
*ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;
|
||||
strcpy(ptr, name);
|
||||
strcpy((char *)ptr, name);
|
||||
ptr += strlen(name) + 1;
|
||||
*ptr++ = BIND_OPCODE_DO_BIND;
|
||||
*ptr = BIND_OPCODE_DONE;
|
||||
@ -1316,7 +1318,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
||||
*ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
|
||||
(BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
|
||||
*ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;
|
||||
strcpy(ptr, name);
|
||||
strcpy((char *)ptr, name);
|
||||
ptr += strlen(name) + 1;
|
||||
*ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;
|
||||
set_segment_and_offset(mo, s->sh_addr, ptr,
|
||||
@ -1582,6 +1584,11 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||
seg->initprot = 3; // rw-
|
||||
seg->flags = SG_READ_ONLY;
|
||||
|
||||
seg = add_segment(mo, "__DWARF");
|
||||
seg->vmaddr = -1;
|
||||
seg->maxprot = 7; // rwx
|
||||
seg->initprot = 3; // rw-
|
||||
|
||||
seg = add_segment(mo, "__DATA");
|
||||
seg->vmaddr = -1;
|
||||
seg->maxprot = 3; // rw-
|
||||
@ -1592,6 +1599,10 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||
seg->maxprot = 1; // r--
|
||||
seg->initprot = 1; // r--
|
||||
|
||||
/* trick to avoid __DWARF vmaddr = -1 */
|
||||
if (dwarf_info_section == NULL)
|
||||
dwarf_info_section = new_section(s1, ".debug_info", SHT_PROGBITS, 0);
|
||||
|
||||
#ifdef CONFIG_NEW_MACHO
|
||||
chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
|
||||
sizeof(struct linkedit_data_command));
|
||||
@ -1638,7 +1649,8 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||
type = s->sh_type;
|
||||
flags = s->sh_flags;
|
||||
sk = sk_unknown;
|
||||
if (flags & SHF_ALLOC) {
|
||||
/* debug sections have sometimes no SHF_ALLOC */
|
||||
if ((flags & SHF_ALLOC) || !strncmp(s->name, ".debug_", 7)) {
|
||||
switch (type) {
|
||||
default: sk = sk_unknown; break;
|
||||
case SHT_INIT_ARRAY: sk = sk_init; break;
|
||||
|
Loading…
Reference in New Issue
Block a user