Better fix for old macho format

The last commit only worked on arm64.

The problem was that the new __DWARF segment was empty.
I now remove the __DWARF segment if it is not needed.
This resolves the rebase problem on x86_64.
This commit is contained in:
herman ten brugge 2022-12-02 22:57:49 +01:00
parent 14e78d7cc2
commit 894e166ecf

View File

@ -422,6 +422,7 @@ struct macho {
Section *symtab, *strtab, *wdata, *indirsyms, *stubs, *exports; Section *symtab, *strtab, *wdata, *indirsyms, *stubs, *exports;
uint32_t ilocal, iextdef, iundef; uint32_t ilocal, iextdef, iundef;
int stubsym, n_got, nr_plt; int stubsym, n_got, nr_plt;
int segment[sk_last];
#ifdef CONFIG_NEW_MACHO #ifdef CONFIG_NEW_MACHO
Section *chained_fixups; Section *chained_fixups;
int n_bind; int n_bind;
@ -1189,14 +1190,14 @@ static void create_symtab(TCCState *s1, struct macho *mo)
} }
const struct { const struct {
int seg; int seg_initial;
uint32_t flags; uint32_t flags;
const char *name; const char *name;
} skinfo[sk_last] = { } skinfo[sk_last] = {
/*[sk_unknown] =*/ { 0 }, /*[sk_unknown] =*/ { 0 },
/*[sk_discard] =*/ { 0 }, /*[sk_discard] =*/ { 0 },
/*[sk_text] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS /*[sk_text] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS, "__text" }, | S_ATTR_SOME_INSTRUCTIONS, "__text" },
/*[sk_stubs] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_SYMBOL_STUBS /*[sk_stubs] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_SYMBOL_STUBS
| S_ATTR_SOME_INSTRUCTIONS , "__stubs" }, | S_ATTR_SOME_INSTRUCTIONS , "__stubs" },
/*[sk_stub_helper] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS /*[sk_stub_helper] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS
@ -1570,6 +1571,9 @@ static void collect_sections(TCCState *s1, struct macho *mo)
struct dysymtab_command *dysymlc; struct dysymtab_command *dysymlc;
char *str; char *str;
for (sk = sk_unknown; sk < sk_last; sk++)
mo->segment[sk] = skinfo[sk].seg_initial;
seg = add_segment(mo, "__PAGEZERO"); seg = add_segment(mo, "__PAGEZERO");
seg->vmsize = (uint64_t)1 << 32; seg->vmsize = (uint64_t)1 << 32;
@ -1584,10 +1588,16 @@ static void collect_sections(TCCState *s1, struct macho *mo)
seg->initprot = 3; // rw- seg->initprot = 3; // rw-
seg->flags = SG_READ_ONLY; seg->flags = SG_READ_ONLY;
seg = add_segment(mo, "__DWARF"); if (dwarf_info_section) {
seg->vmaddr = -1; seg = add_segment(mo, "__DWARF");
seg->maxprot = 7; // rwx seg->vmaddr = -1;
seg->initprot = 3; // rw- seg->maxprot = 7; // rwx
seg->initprot = 3; // rw-
}
else
for (sk = sk_unknown; sk < sk_last; sk++)
if (mo->segment[sk] >= 4)
mo->segment[sk]--;
seg = add_segment(mo, "__DATA"); seg = add_segment(mo, "__DATA");
seg->vmaddr = -1; seg->vmaddr = -1;
@ -1599,10 +1609,6 @@ static void collect_sections(TCCState *s1, struct macho *mo)
seg->maxprot = 1; // r-- seg->maxprot = 1; // r--
seg->initprot = 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 #ifdef CONFIG_NEW_MACHO
chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
sizeof(struct linkedit_data_command)); sizeof(struct linkedit_data_command));
@ -1714,15 +1720,8 @@ static void collect_sections(TCCState *s1, struct macho *mo)
for (sk = sk_unknown; sk < sk_last; sk++) { for (sk = sk_unknown; sk < sk_last; sk++) {
struct section_64 *sec = NULL; struct section_64 *sec = NULL;
if (seg) { if (seg) {
#ifdef CONFIG_NEW_MACHO
seg->vmsize = curaddr - seg->vmaddr; seg->vmsize = curaddr - seg->vmaddr;
seg->filesize = fileofs - seg->fileoff; seg->filesize = fileofs - seg->fileoff;
#else
seg->vmsize = (curaddr - seg->vmaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
seg->filesize = (fileofs - seg->fileoff + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
curaddr = seg->vmaddr + seg->vmsize;
fileofs = seg->fileoff + seg->filesize;
#endif
} }
#ifdef CONFIG_NEW_MACHO #ifdef CONFIG_NEW_MACHO
if (sk == sk_linkedit) { if (sk == sk_linkedit) {
@ -1735,14 +1734,14 @@ static void collect_sections(TCCState *s1, struct macho *mo)
export_trie(s1, mo); export_trie(s1, mo);
} }
#endif #endif
if (skinfo[sk].seg && mo->sk_to_sect[sk].s) { if (mo->segment[sk] && mo->sk_to_sect[sk].s) {
uint64_t al = 0; uint64_t al = 0;
int si; int si;
seg = get_segment(mo, skinfo[sk].seg); seg = get_segment(mo, mo->segment[sk]);
if (skinfo[sk].name) { if (skinfo[sk].name) {
si = add_section(mo, &seg, skinfo[sk].name); si = add_section(mo, &seg, skinfo[sk].name);
numsec++; numsec++;
mo->lc[mo->seg2lc[skinfo[sk].seg]] = (struct load_command*)seg; mo->lc[mo->seg2lc[mo->segment[sk]]] = (struct load_command*)seg;
mo->sk_to_sect[sk].machosect = si; mo->sk_to_sect[sk].machosect = si;
sec = get_section(seg, si); sec = get_section(seg, si);
sec->flags = skinfo[sk].flags; sec->flags = skinfo[sk].flags;
@ -1760,17 +1759,10 @@ static void collect_sections(TCCState *s1, struct macho *mo)
#endif #endif
} }
if (seg->vmaddr == -1) { if (seg->vmaddr == -1) {
#ifdef CONFIG_NEW_MACHO
curaddr = (curaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE; curaddr = (curaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
seg->vmaddr = curaddr; seg->vmaddr = curaddr;
fileofs = (fileofs + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE; fileofs = (fileofs + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
seg->fileoff = fileofs; seg->fileoff = fileofs;
#else
curaddr = (curaddr + 4095) & -4096;
seg->vmaddr = curaddr;
fileofs = (fileofs + 4095) & -4096;
seg->fileoff = fileofs;
#endif
} }
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
@ -1913,9 +1905,9 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
for (sk = sk_unknown; sk < sk_last; sk++) { for (sk = sk_unknown; sk < sk_last; sk++) {
//struct segment_command_64 *seg; //struct segment_command_64 *seg;
if (!skinfo[sk].seg || !mo->sk_to_sect[sk].s) if (!mo->segment[sk] || !mo->sk_to_sect[sk].s)
continue; continue;
/*seg =*/ get_segment(mo, skinfo[sk].seg); /*seg =*/ get_segment(mo, mo->segment[sk]);
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
if (s->sh_type != SHT_NOBITS) { if (s->sh_type != SHT_NOBITS) {
while (fileofs < s->sh_offset) while (fileofs < s->sh_offset)