Good evening. For several month i was trying to salvage tccboot JiT and AoT compilation of linux-2.4 kernel. This covered a notable amount of test-cases, and didn't yield a stable known-good baseline with any, to emit a bootable kernel. Recently i could identify a somewhat severe regression in tcc introduced may 2022, commit-id 8e860702e44ca1279098e0fc2142ad579774b1d2
Reverting this commit shows linux-2.4.37.11 can be compiled,linked and booted without problems. Too rebasing this backout/revert up until october 2024 (commit c21576f8a32715ab439690d18184b0e02022bbbd) was possible and linux-2.4 compiled/linked with tcc then booted flawlessly again. Linux-2.4 kernel compilation seems a reasonable test-case, hence it was introduced by Fabrice 20 years ago with tccboot too. And the regression that broke compilation/linking of kernel went unnoticed for more than 2 years on mob branch. Instead of reverting/backing-out the mentioned change on mob branch maybe it's possible to address the issue by fixing the regression. The revert/backout diff that i could confirm that tcc succeeds compiling/linking kernel with is attached. --
reverted and rebased commit 8e860702e44ca1279098e0fc2142ad579774b1d2
onto c21576f8a32715ab439690d18184b0e02022bbbd
any later version yields further merge conflicts
otherwise linux-2.4 compiled/linked with tcc causes a kernel crash
if the commit is not reverted
diff --git a/tccelf.c b/tccelf.c
index c01854ad..ef38662f 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -49,10 +49,10 @@ struct sym_version {
#ifdef TCC_TARGET_PE
#define shf_RELRO SHF_ALLOC
-static const char rdata[] = ".rdata";
+//static const char rdata[] = ".rdata";
#else
#define shf_RELRO s1->shf_RELRO
-static const char rdata[] = ".data.ro";
+//static const char rdata[] = ".data.ro";
#endif
/* ------------------------------------------------------------------------- */
@@ -73,8 +73,12 @@ ST_FUNC void tccelf_new(TCCState *s)
/* create standard sections */
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC |
SHF_EXECINSTR);
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC |
SHF_WRITE);
+#ifdef TCC_TARGET_PE
+ rodata_section = new_section(s, ".rdata", SHT_PROGBITS, SHF_ALLOC);
+#else
/* create ro data section (make ro after relocation done with GNU_RELRO) */
- rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
+ rodata_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC |
SHF_WRITE);
+#endif
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
common_section->sh_num = SHN_COMMON;
@@ -99,8 +103,10 @@ ST_FUNC void tccelf_new(TCCState *s)
if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */
/* (make ro after relocation done with GNU_RELRO) */
- bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
- lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
+ bounds_section = new_section(s, ".bounds",
+ SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+ lbounds_section = new_section(s, ".lbounds",
+ SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
}
#endif
}
@@ -1502,8 +1508,10 @@ ST_FUNC void add_array (TCCState *s1, const char *sec,
int c)
{
Section *s;
s = find_section(s1, sec);
- s->sh_flags = shf_RELRO;
+ s->sh_flags |= SHF_WRITE;
+#ifndef TCC_TARGET_PE
s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY;
+#endif
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
section_ptr_add(s, PTR_SIZE);
}
@@ -1815,7 +1823,9 @@ static void tcc_add_linker_symbols(TCCState *s1)
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
#endif
/* horrible new standard ldscript defines */
+#ifndef TCC_TARGET_PE
add_init_array_defines(s1, ".preinit_array");
+#endif
add_init_array_defines(s1, ".init_array");
add_init_array_defines(s1, ".fini_array");
/* add start and stop symbols for sections whose name can be
@@ -2110,179 +2120,61 @@ static int set_sec_sizes(TCCState *s1)
return textrel;
}
-/* various data used under elf_output_file() */
+
+/* Info to be copied in dynamic section */
struct dyn_inf {
Section *dynamic;
Section *dynstr;
- struct {
- /* Info to be copied in dynamic section */
- unsigned long data_offset;
- addr_t rel_addr;
- addr_t rel_size;
- };
- ElfW(Phdr) *phdr;
- int phnum;
- Section *interp;
- Section *note;
Section *gnu_hash;
- /* read only segment mapping for GNU_RELRO */
- Section _roinf, *roinf;
+ unsigned long data_offset;
+ addr_t rel_addr;
+ addr_t rel_size;
};
-/* Decide the layout of sections loaded in memory. This must be done before
- program headers are filled since they contain info about the layout.
- We do the following ordering: interp, symbol tables, relocations, progbits,
- nobits */
-static int sort_sections(TCCState *s1, int *sec_order, Section *interp)
-{
- Section *s;
- int i, j, k, f, f0, n;
- int nb_sections = s1->nb_sections;
- int *sec_cls = sec_order + nb_sections;
-
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_flags & SHF_ALLOC) {
- j = 0x100;
- if (s->sh_flags & SHF_WRITE)
- j = 0x200;
- if (s->sh_flags & SHF_TLS)
- j += 0x200;
- } else if (s->sh_name) {
- j = 0x700;
- } else {
- j = 0x900; /* no sh_name: won't go to file */
- }
- if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
- k = 0x10;
- } else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) {
- k = 0x11;
- if (i == nb_sections - 1) /* ".shstrtab" assumed to remain last */
- k = 0xff;
- } else if (s->sh_type == SHT_HASH || s->sh_type == SHT_GNU_HASH) {
- k = 0x12;
- } else if (s->sh_type == SHT_RELX) {
- k = 0x20;
- if (s1->plt && s == s1->plt->reloc)
- k = 0x21;
- } else if (s->sh_type == SHT_PREINIT_ARRAY) {
- k = 0x41;
- } else if (s->sh_type == SHT_INIT_ARRAY) {
- k = 0x42;
- } else if (s->sh_type == SHT_FINI_ARRAY) {
- k = 0x43;
-#ifdef CONFIG_TCC_BCHECK
- } else if (s == bounds_section || s == lbounds_section) {
- k = 0x44;
-#endif
- } else if (s == rodata_section || 0 == strcmp(s->name,
".data.rel.ro")) {
- k = 0x45;
- } else if (s->sh_type == SHT_DYNAMIC) {
- k = 0x46;
- } else if (s == s1->got) {
- k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
- } else {
- k = 0x50;
- if (s->sh_type == SHT_NOTE)
- k = 0x60;
- if (s->sh_flags & SHF_EXECINSTR)
- k = 0x70;
- if (s->sh_type == SHT_NOBITS)
- k = 0x80;
- if (s == interp)
- k = 0x00;
- }
- k += j;
-
- for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n)
- sec_cls[n] = f, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
- }
- sec_order[0] = 0;
+/* Info for GNU_RELRO */
+struct ro_inf {
+ addr_t sh_offset;
+ addr_t sh_addr;
+ addr_t sh_size;
+};
- /* count PT_LOAD headers needed */
- n = f0 = 0;
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- k = sec_cls[i];
- f = 0;
- if (k < 0x700) {
- f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
-#if TARGETOS_NetBSD
- /* NetBSD only supports 2 PT_LOAD sections.
- See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
- if ((f & SHF_WRITE) == 0) f |= SHF_EXECINSTR;
-#else
- if ((k & 0xfff0) == 0x240) /* RELRO sections */
- f |= 1<<4;
-#endif
- if (f != f0) /* start new header when flags changed or relro */
- f0 = f, ++n, f |= 1<<8;
- }
- sec_cls[i] = f;
- //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", !!f * n, i, f,
k, s->sh_type, s->sh_size, s->name);
- }
- return n;
-}
+static void alloc_sec_names(
+ TCCState *s1, int is_obj
+ );
-static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s)
-{
- if (s) {
- ph->p_offset = s->sh_offset;
- ph->p_vaddr = s->sh_addr;
- ph->p_filesz = s->sh_size;
- ph->p_align = s->sh_addralign;
- }
- ph->p_type = type;
- ph->p_flags = PF_R;
- ph->p_paddr = ph->p_vaddr;
- ph->p_memsz = ph->p_filesz;
- return ph;
-}
+static int layout_any_sections(
+ TCCState *s1, int file_offset, int *sec_order, int is_obj
+ );
/* Assign sections to segments and decide how are sections laid out when loaded
in memory. This function also fills corresponding program headers. */
-static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
+static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
+ int phnum, int phfill,
+ Section *interp,
+ struct ro_inf *roinf, int *sec_order)
{
+ int i, file_offset;
Section *s;
- addr_t addr, tmp, align, s_align, base;
- ElfW(Phdr) *ph = NULL;
- int i, f, n, phnum, phfill;
- int file_offset;
-
- /* compute number of program headers */
- phnum = sort_sections(s1, sec_order, d->interp);
- phfill = 0; /* set to 1 to have dll's with a PT_PHDR */
- if (d->interp)
- phfill = 2;
- phnum += phfill;
- if (d->note)
- ++phnum;
- if (d->dynamic)
- ++phnum;
- if (d->roinf)
- ++phnum;
- d->phnum = phnum;
- d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
file_offset = 0;
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
+ {
+ unsigned long s_align;
+ long long tmp;
+ addr_t addr;
+ ElfW(Phdr) *ph;
+ int j, k, f, file_type = s1->output_type;
- s_align = ELF_PAGE_SIZE;
- if (s1->section_align)
- s_align = s1->section_align;
-
- addr = ELF_START_ADDR;
- if (s1->output_type & TCC_OUTPUT_DYN)
- addr = 0;
+ s_align = ELF_PAGE_SIZE;
+ if (s1->section_align)
+ s_align = s1->section_align;
- if (s1->has_text_addr) {
- addr = s1->text_addr;
- if (0) {
+ if (s1->has_text_addr) {
int a_offset, p_offset;
+ addr = s1->text_addr;
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
ELF_PAGE_SIZE */
a_offset = (int) (addr & (s_align - 1));
@@ -2290,109 +2182,163 @@ static int layout_sections(TCCState *s1, int
*sec_order, struct dyn_inf *d)
if (a_offset < p_offset)
a_offset += s_align;
file_offset += (a_offset - p_offset);
+ } else {
+ if (file_type & TCC_OUTPUT_DYN)
+ addr = 0;
+ else
+ addr = ELF_START_ADDR;
+ /* compute address after headers */
+ addr += (file_offset & (s_align - 1));
}
- }
- base = addr;
- /* compute address after headers */
- addr = addr + (file_offset & (s_align - 1));
- n = 0;
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- f = sec_order[i + s1->nb_sections];
- align = s->sh_addralign - 1;
-
- if (f == 0) { /* no alloc */
- file_offset = (file_offset + align) & ~align;
- s->sh_offset = file_offset;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
- continue;
- }
+ ph = &phdr[0];
+ /* Leave one program headers for the program interpreter and one for
+ the program header table itself if needed. These are done later as
+ they require section layout to be done first. */
+ if (interp)
+ ph += 2;
- if ((f & 1<<8) && n) {
- /* different rwx section flags */
- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
- /* if in the middle of a page, w e duplicate the page in
- memory so that one copy is RX and the other is RW */
- if ((addr & (s_align - 1)) != 0)
- addr += s_align;
- } else {
- align = s_align - 1;
- }
- }
+ /* read only segment mapping for GNU_RELRO */
+ roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
- tmp = addr;
- addr = (addr + align) & ~align;
- file_offset += (int)(addr - tmp);
- s->sh_offset = file_offset;
- s->sh_addr = addr;
-
- if (f & 1<<8) {
- /* set new program header */
- ph = &d->phdr[phfill + n];
- ph->p_type = PT_LOAD;
- ph->p_align = s_align;
- ph->p_flags = PF_R;
- if (f & SHF_WRITE)
- ph->p_flags |= PF_W;
- if (f & SHF_EXECINSTR)
- ph->p_flags |= PF_X;
- if (f & SHF_TLS) {
- ph->p_type = PT_TLS;
- ph->p_align = align + 1;
- }
+ for(j = 0; j < phfill; j++) {
+ ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
+ if (j == 0)
+ ph->p_flags = PF_R | PF_X;
+ else
+ ph->p_flags = PF_R | PF_W;
+ ph->p_align = j == 2 ? 4 : s_align;
+
+ /* Decide the layout of sections loaded in memory. This must
+ be done before program headers are filled since they contain
+ info about the layout. We do the following ordering: interp,
+ symbol tables, relocations, progbits, nobits */
+ /* XXX: do faster and simpler sorting */
+ f = -1;
+ for(k = 0; k < 10; k++) {
+ for(i = 1; i < s1->nb_sections; i++) {
+ s = s1->sections[i];
+ /* compute if section should be included */
+ if (j == 0) {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ SHF_ALLOC)
+ continue;
+ } else if (j == 1) {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ (SHF_ALLOC | SHF_WRITE))
+ continue;
+ } else {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ (SHF_ALLOC | SHF_WRITE | SHF_TLS))
+ continue;
+ }
+ if (s == interp) {
+ if (k != 0)
+ continue;
+ } else if ((s->sh_type == SHT_DYNSYM ||
+ s->sh_type == SHT_STRTAB ||
+ s->sh_type == SHT_HASH)
+ && !strstr(s->name, ".stab")) {
+ if (k != 1)
+ continue;
+ } else if (s->sh_type == SHT_RELX) {
+ if (s1->plt && s == s1->plt->reloc) {
+ if (k != 3)
+ continue;
+ } else {
+ if (k != 2)
+ continue;
+ }
+ } else if ((s == rodata_section
+#ifdef CONFIG_TCC_BCHECK
+ || s == bounds_section
+ || s == lbounds_section
+#endif
+ ) && (s->sh_flags & SHF_WRITE)) {
+ if (k != 4)
+ continue;
+ /* Align next section on page size.
+ This is needed to remap roinf section ro. */
+ f = 1;
+
+ } else if (s->sh_type == SHT_PREINIT_ARRAY) {
+ if (k != 6)
+ continue;
+ } else if (s->sh_type == SHT_INIT_ARRAY) {
+ if (k != 7)
+ continue;
+ } else if (s->sh_type == SHT_FINI_ARRAY) {
+ if (k != 8)
+ continue;
+ } else if (s->sh_type == SHT_NOBITS) {
+ if (k != 9)
+ continue;
+ } else {
+ if (k != 5)
+ continue;
+ }
+ *sec_order++ = i;
+
+ /* section matches: we align it and add its size */
+ tmp = addr;
+ if (f-- == 0)
+ s->sh_addralign = PAGESIZE;
+ addr = (addr + s->sh_addralign - 1) &
+ ~(s->sh_addralign - 1);
+ file_offset += (int) ( addr - tmp );
+ s->sh_offset = file_offset;
+ s->sh_addr = addr;
+
+ /* update program header infos */
+ if (ph->p_offset == 0) {
+ ph->p_offset = file_offset;
+ ph->p_vaddr = addr;
+ ph->p_paddr = ph->p_vaddr;
+ }
+
+ if (k == 4) {
+ if (roinf->sh_size == 0) {
+ roinf->sh_offset = s->sh_offset;
+ roinf->sh_addr = s->sh_addr;
+ }
+ roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
+ }
+
+ addr += s->sh_size;
+ if (s->sh_type != SHT_NOBITS)
+ file_offset += s->sh_size;
+ }
+ } //
- ph->p_offset = file_offset;
- ph->p_vaddr = addr;
- if (n == 0) {
+ if (j == 0) {
/* Make the first PT_LOAD segment include the program
headers itself (and the ELF header as well), it'll
come out with same memory use but will make various
tools like binutils strip work better. */
- ph->p_offset = 0;
- ph->p_vaddr = base;
- }
- ph->p_paddr = ph->p_vaddr;
- ++n;
- }
- if (f & 1<<4) {
- Section *roinf = &d->_roinf;
- if (roinf->sh_size == 0) {
- roinf->sh_offset = s->sh_offset;
- roinf->sh_addr = s->sh_addr;
- roinf->sh_addralign = 1;
+ ph->p_offset &= ~(ph->p_align - 1);
+ ph->p_vaddr &= ~(ph->p_align - 1);
+ ph->p_paddr &= ~(ph->p_align - 1);
}
- roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
+ ph->p_filesz = file_offset - ph->p_offset;
+ ph->p_memsz = addr - ph->p_vaddr;
+ ph++;
+ if (j == 0) {
+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
+ /* if in the middle of a page, we duplicate the page in
+ memory so that one copy is RX and the other is RW */
+ if ((addr & (s_align - 1)) != 0)
+ addr += s_align;
+ } else {
+ addr = (addr + s_align - 1) & ~(s_align - 1);
+ file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
+ }
+ }
}
-
- addr += s->sh_size;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
-
- ph->p_filesz = file_offset - ph->p_offset;
- ph->p_memsz = addr - ph->p_vaddr;
- }
-
- /* Fill other headers */
- if (d->note)
- fill_phdr(++ph, PT_NOTE, d->note);
- if (d->dynamic)
- fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
- if (d->roinf)
- fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
- if (d->interp)
- fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
- if (phfill) {
- ph = &d->phdr[0];
- ph->p_offset = sizeof(ElfW(Ehdr));
- ph->p_vaddr = base + ph->p_offset;
- ph->p_filesz = phnum * sizeof(ElfW(Phdr));
- ph->p_align = 4;
- fill_phdr(ph, PT_PHDR, NULL);
}
- return file_offset;
+
+ /* all other sections come after */
+ return layout_any_sections(s1, file_offset, sec_order, 0);
}
/* put dynamic tag */
@@ -2404,6 +2350,75 @@ static void put_dt(Section *dynamic, int dt, addr_t val)
dyn->d_un.d_val = val;
}
+static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
+ Section *dynamic, Section *note, struct
ro_inf *roinf)
+{
+ ElfW(Phdr) *ph;
+
+ /* if interpreter, then add corresponding program header */
+ if (interp) {
+ ph = &phdr[0];
+
+ ph->p_type = PT_PHDR;
+ ph->p_offset = sizeof(ElfW(Ehdr));
+ ph->p_filesz = ph->p_memsz = phnum * sizeof(ElfW(Phdr));
+ ph->p_vaddr = interp->sh_addr - ph->p_filesz;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_flags = PF_R | PF_X;
+ ph->p_align = 4; /* interp->sh_addralign; */
+ ph++;
+
+ ph->p_type = PT_INTERP;
+ ph->p_offset = interp->sh_offset;
+ ph->p_vaddr = interp->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = interp->sh_size;
+ ph->p_memsz = interp->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = interp->sh_addralign;
+ }
+
+ if (note) {
+ ph = &phdr[phnum - 2 - (roinf != NULL)];
+
+ ph->p_type = PT_NOTE;
+ ph->p_offset = note->sh_offset;
+ ph->p_vaddr = note->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = note->sh_size;
+ ph->p_memsz = note->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = note->sh_addralign;
+ }
+
+ /* if dynamic section, then add corresponding program header */
+ if (dynamic) {
+ ph = &phdr[phnum - 1 - (roinf != NULL)];
+
+ ph->p_type = PT_DYNAMIC;
+ ph->p_offset = dynamic->sh_offset;
+ ph->p_vaddr = dynamic->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = dynamic->sh_size;
+ ph->p_memsz = dynamic->sh_size;
+ ph->p_flags = PF_R | PF_W;
+ ph->p_align = dynamic->sh_addralign;
+ }
+
+ if (roinf) {
+ ph = &phdr[phnum - 1];
+
+ ph->p_type = PT_GNU_RELRO;
+ ph->p_offset = roinf->sh_offset;
+ ph->p_vaddr = roinf->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = roinf->sh_size;
+ ph->p_memsz = roinf->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = 1;
+ }
+}
+
/* Fill the dynamic section with tags describing the address and size of
sections */
static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
@@ -2506,7 +2521,6 @@ static void update_reloc_sections(TCCState *s1, struct
dyn_inf *dyninf)
}
}
-static int tidy_section_headers(TCCState *s1, int *sec_order);
#endif /* ndef ELF_OBJ_ONLY */
/* Create an ELF file on disk.
@@ -2528,9 +2542,6 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
ehdr.e_phentsize = sizeof(ElfW(Phdr));
ehdr.e_phnum = phnum;
ehdr.e_phoff = sizeof(ElfW(Ehdr));
-#ifndef ELF_OBJ_ONLY
- shnum = tidy_section_headers(s1, sec_order);
-#endif
}
/* align to 4 */
@@ -2590,8 +2601,8 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
sort_syms(s1, symtab_section);
- for(i = 1; i < shnum; i++) {
- s = s1->sections[sec_order ? sec_order[i] : i];
+ for(i = 1; i < s1->nb_sections; i++) {
+ s = s1->sections[sec_order[i]];
if (s->sh_type != SHT_NOBITS) {
while (offset < s->sh_offset) {
fputc(0, f);
@@ -2610,7 +2621,7 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
offset++;
}
- for(i = 0; i < shnum; i++) {
+ for(i = 0; i < s1->nb_sections; i++) {
sh = &shdr;
memset(sh, 0, sizeof(ElfW(Shdr)));
s = s1->sections[i];
@@ -2690,7 +2701,7 @@ static int tcc_write_elf_file(TCCState *s1, const char
*filename, int phnum,
#ifndef ELF_OBJ_ONLY
/* Sort section headers by assigned sh_addr, remove sections
that we aren't going to output. */
-static int tidy_section_headers(TCCState *s1, int *sec_order)
+static void tidy_section_headers(TCCState *s1, int *sec_order)
{
int i, nnew, l, *backmap;
Section **snew, *s;
@@ -2730,8 +2741,8 @@ static int tidy_section_headers(TCCState *s1, int
*sec_order)
sec_order[i] = i;
tcc_free(s1->sections);
s1->sections = snew;
+ s1->nb_sections = nnew;
tcc_free(backmap);
- return nnew;
}
#ifdef TCC_TARGET_ARM
@@ -2797,33 +2808,34 @@ static void alloc_sec_names(TCCState *s1, int is_obj);
/* XXX: suppress unneeded sections */
static int elf_output_file(TCCState *s1, const char *filename)
{
- int i, ret, file_type, file_offset, *sec_order;
+ int i, ret, phnum, phfill, shnum, file_type, file_offset, *sec_order;
struct dyn_inf dyninf = {0};
- Section *interp, *dynstr, *dynamic;
+ struct ro_inf roinf;
+ ElfW(Phdr) *phdr;
+ Section *interp, *dynamic, *dynstr, *note;
+ struct ro_inf *roinf_use = NULL;
int textrel, got_sym, dt_flags_1;
file_type = s1->output_type;
s1->nb_errors = 0;
ret = -1;
- interp = dynstr = dynamic = NULL;
+ phdr = NULL;
sec_order = NULL;
- dyninf.roinf = &dyninf._roinf;
+ interp = dynamic = dynstr = note = NULL;
#ifdef TCC_TARGET_ARM
create_arm_attribute_section (s1);
#endif
#if TARGETOS_OpenBSD
- dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident",
"OpenBSD");
+ note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
#endif
#if TARGETOS_NetBSD
- dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
+ note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
#endif
-#if TARGETOS_FreeBSD || TARGETOS_NetBSD
- dyninf.roinf = NULL;
-#endif
+ {
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
tcc_add_runtime(s1);
resolve_common_syms(s1);
@@ -2840,7 +2852,6 @@ static int elf_output_file(TCCState *s1, const char
*filename)
interp->sh_addralign = 1;
ptr = section_ptr_add(interp, 1 + strlen(elfint));
strcpy(ptr, elfint);
- dyninf.interp = interp;
}
/* add dynamic symbol table */
@@ -2874,6 +2885,7 @@ static int elf_output_file(TCCState *s1, const char
*filename)
build_got_entries(s1, 0);
}
version_add (s1);
+ }
textrel = set_sec_sizes(s1);
alloc_sec_names(s1, 0);
@@ -2915,11 +2927,36 @@ static int elf_output_file(TCCState *s1, const char
*filename)
dynstr->sh_size = dynstr->data_offset;
}
+ /* compute number of program headers */
+ phfill = 2;
+ for (i = 1; i < s1->nb_sections; i++)
+ if (s1->sections[i]->sh_flags & SHF_TLS)
+ phfill = 3;
+ phnum = 3;
+ if (interp)
+ phnum += phfill;
+ if (note)
+ phnum++;
+#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD
+ /* GNU_RELRO */
+ phnum++, roinf_use = &roinf;
+#endif
+
+ /* allocate program segment headers */
+ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
+ /* compute number of sections */
+ shnum = s1->nb_sections;
/* this array is used to reorder sections in the output file */
- sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
+ sec_order = tcc_malloc(sizeof(int) * shnum);
+ sec_order[0] = 0;
+
/* compute section to program header mapping */
- file_offset = layout_sections(s1, sec_order, &dyninf);
+ file_offset = layout_sections(s1, phdr, phnum, phfill, interp, &roinf,
sec_order + 1);
+ /* Fill remaining program header and finalize relocation related to dynamic
+ linking. */
+ {
+ fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
if (dynamic) {
/* put in GOT the dynamic section address and relocate PLT */
write32le(s1->got->data, dynamic->sh_addr);
@@ -2933,6 +2970,7 @@ static int elf_output_file(TCCState *s1, const char
*filename)
/* if building executable or DLL, then relocate each section
except the GOT which is already relocated */
relocate_syms(s1, s1->symtab, 0);
+ ret = -1;
if (s1->nb_errors != 0)
goto the_end;
relocate_sections(s1);
@@ -2941,20 +2979,25 @@ static int elf_output_file(TCCState *s1, const char
*filename)
dynamic->data_offset = dyninf.data_offset;
fill_dynamic(s1, &dyninf);
}
+ tidy_section_headers(s1, sec_order);
+
/* Perform relocation to GOT or PLT entries */
if (file_type == TCC_OUTPUT_EXE && s1->static_link)
fill_got(s1);
else if (s1->got)
fill_local_got_entries(s1);
+ }
+
if (dyninf.gnu_hash)
update_gnu_hash(s1, dyninf.gnu_hash);
/* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr,
file_offset, sec_order);
+ ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order
);
+ s1->nb_sections = shnum;
the_end:
tcc_free(sec_order);
- tcc_free(dyninf.phdr);
+ tcc_free(phdr);
return ret;
}
#endif /* ndef ELF_OBJ_ONLY */
@@ -2977,24 +3020,42 @@ static void alloc_sec_names(TCCState *s1, int is_obj)
strsec->sh_size = strsec->data_offset;
}
-/* Output an elf .o file */
-static int elf_output_obj(TCCState *s1, const char *filename)
+static int layout_any_sections(TCCState *s1, int file_offset, int *sec_order,
int is_obj)
{
+ int i;
Section *s;
- int i, ret, file_offset;
- s1->nb_errors = 0;
- /* Allocate strings for section names */
- alloc_sec_names(s1, 1);
- file_offset = sizeof (ElfW(Ehdr));
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
- file_offset = (file_offset + 15) & -16;
+ if (!is_obj && (s->sh_flags & SHF_ALLOC))
+ continue;
+ *sec_order++ = i;
+ file_offset = (file_offset + s->sh_addralign - 1) &
+ ~(s->sh_addralign - 1);
s->sh_offset = file_offset;
if (s->sh_type != SHT_NOBITS)
file_offset += s->sh_size;
}
+ return file_offset;
+}
+
+/* Output an elf .o file */
+static int elf_output_obj(TCCState *s1, const char *filename)
+{
+ int ret, file_offset;
+ int *sec_order;
+ s1->nb_errors = 0;
+
+ /* Allocate strings for section names */
+ alloc_sec_names(s1, 1);
+
+ /* this array is used to reorder sections in the output file */
+ sec_order = tcc_malloc(sizeof(int) * s1->nb_sections);
+ sec_order[0] = 0;
+ file_offset = layout_any_sections(s1, sizeof (ElfW(Ehdr)), sec_order + 1,
1);
+
/* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, NULL);
+ ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, sec_order);
+ tcc_free(sec_order);
return ret;
}
diff --git a/tccpe.c b/tccpe.c
index c87814d3..1bcb7435 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -1137,9 +1137,7 @@ static int pe_section_class(Section *s)
return sec_debug;
} else if (flags & SHF_ALLOC) {
- if (type == SHT_PROGBITS
- || type == SHT_INIT_ARRAY
- || type == SHT_FINI_ARRAY) {
+ if (type == SHT_PROGBITS) {
if (flags & SHF_EXECINSTR)
return sec_text;
if (flags & SHF_WRITE)
@@ -1152,44 +1150,52 @@ static int pe_section_class(Section *s)
return sec_pdata;
return sec_rdata;
} else if (type == SHT_NOBITS) {
- return sec_bss;
+ if (flags & SHF_WRITE)
+ return sec_bss;
}
- return sec_other;
} else {
if (0 == strcmp(name, ".reloc"))
return sec_reloc;
}
- return sec_last;
+ if (0 == memcmp(name, ".stab", 5))
+ return name[5] ? sec_stabstr : sec_stab;
+ if (flags & SHF_ALLOC)
+ return sec_other;
+ return -1;
}
static int pe_assign_addresses (struct pe_info *pe)
{
- int i, k, n, c, nbs;
+ int i, k, o, c;
ADDR3264 addr;
- int *sec_order, *sec_cls;
+ int *section_order;
struct section_info *si;
Section *s;
TCCState *s1 = pe->s1;
if (PE_DLL == pe->type)
pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
- //pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
-
- nbs = s1->nb_sections;
- sec_order = tcc_mallocz(2 * sizeof (int) * nbs);
- sec_cls = sec_order + nbs;
- for (i = 1; i < nbs; ++i) {
- s = s1->sections[i];
- k = pe_section_class(s);
- for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n)
- sec_cls[n] = c, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
+ // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
+
+ section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
+ for (o = k = 0 ; k < sec_last; ++k) {
+ for (i = 1; i < s1->nb_sections; ++i) {
+ s = s1->sections[i];
+ if (k == pe_section_class(s))
+ section_order[o++] = i;
+ }
}
+
si = NULL;
addr = pe->imagebase + 1;
- for (i = 1; (c = sec_cls[i]) < sec_last; ++i) {
- s = s1->sections[sec_order[i]];
+ for (i = 0; i < o; ++i) {
+ k = section_order[i];
+ s = s1->sections[k];
+ c = pe_section_class(s);
+
+ if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug)
+ continue;
if (PE_MERGE_DATA && c == sec_bss)
c = sec_data;
@@ -1250,31 +1256,28 @@ add_section:
}
//printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size,
si->pe_flags, s->name);
}
+ tcc_free(section_order);
#if 0
- for (i = 1; i < nbs; ++i) {
- Section *s = s1->sections[sec_order[i]];
+ for (i = 1; i < s1->nb_sections; ++i) {
+ Section *s = s1->sections[i];
int type = s->sh_type;
int flags = s->sh_flags;
printf("section %-16s %-10s %p %04x %s,%s,%s\n",
s->name,
type == SHT_PROGBITS ? "progbits" :
- type == SHT_INIT_ARRAY ? "initarr" :
- type == SHT_FINI_ARRAY ? "finiarr" :
type == SHT_NOBITS ? "nobits" :
type == SHT_SYMTAB ? "symtab" :
type == SHT_STRTAB ? "strtab" :
type == SHT_RELX ? "rel" : "???",
s->sh_addr,
- (unsigned)s->data_offset,
+ s->data_offset,
flags & SHF_ALLOC ? "alloc" : "",
flags & SHF_WRITE ? "write" : "",
flags & SHF_EXECINSTR ? "exec" : ""
);
- fflush(stdout);
}
s1->verbose = 2;
#endif
- tcc_free(sec_order);
return 0;
}
diff --git a/tccelf.c b/tccelf.c
index e6d5bc0..ed51d68 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -47,14 +47,6 @@ struct sym_version {
/* section is dynsymtab_section */
#define SHF_DYNSYM 0x40000000
-#ifdef TCC_TARGET_PE
-static const int shf_RELRO = SHF_ALLOC;
-static const char rdata[] = ".rdata";
-#else
-static const int shf_RELRO = SHF_ALLOC | SHF_WRITE;
-static const char rdata[] = ".data.ro";
-#endif
-
/* ------------------------------------------------------------------------- */
ST_FUNC void tccelf_new(TCCState *s)
@@ -66,8 +58,12 @@ ST_FUNC void tccelf_new(TCCState *s)
/* create standard sections */
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC |
SHF_EXECINSTR);
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC |
SHF_WRITE);
+#ifdef TCC_TARGET_PE
+ rodata_section = new_section(s, ".rdata", SHT_PROGBITS, SHF_ALLOC);
+#else
/* create ro data section (make ro after relocation done with GNU_RELRO) */
- rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
+ rodata_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC |
SHF_WRITE);
+#endif
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
common_section->sh_num = SHN_COMMON;
@@ -90,8 +86,10 @@ ST_FUNC void tccelf_bounds_new(TCCState *s)
{
TCCState *s1 = s;
/* create bounds sections (make ro after relocation done with GNU_RELRO) */
- bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
- lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
+ bounds_section = new_section(s, ".bounds",
+ SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+ lbounds_section = new_section(s, ".lbounds",
+ SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
}
#endif
@@ -1311,8 +1309,10 @@ ST_FUNC void add_array (TCCState *s1, const char *sec,
int c)
{
Section *s;
s = find_section(s1, sec);
- s->sh_flags = shf_RELRO;
+ s->sh_flags |= SHF_WRITE;
+#ifndef TCC_TARGET_PE
s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY;
+#endif
put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
section_ptr_add(s, PTR_SIZE);
}
@@ -1554,7 +1554,9 @@ static void tcc_add_linker_symbols(TCCState *s1)
set_global_sym(s1, "__global_pointer$", data_section, 0x800);
#endif
/* horrible new standard ldscript defines */
+#ifndef TCC_TARGET_PE
add_init_array_defines(s1, ".preinit_array");
+#endif
add_init_array_defines(s1, ".init_array");
add_init_array_defines(s1, ".fini_array");
/* add start and stop symbols for sections whose name can be
@@ -1847,172 +1849,59 @@ static int set_sec_sizes(TCCState *s1)
return textrel;
}
-/* various data used under elf_output_file() */
+
+/* Info to be copied in dynamic section */
struct dyn_inf {
Section *dynamic;
Section *dynstr;
- struct {
- /* Info to be copied in dynamic section */
- unsigned long data_offset;
- addr_t rel_addr;
- addr_t rel_size;
- };
-
- ElfW(Phdr) *phdr;
- int phnum;
- Section *interp;
- Section *note;
-
- /* read only segment mapping for GNU_RELRO */
- Section _roinf, *roinf;
+ unsigned long data_offset;
+ addr_t rel_addr;
+ addr_t rel_size;
};
-/* Decide the layout of sections loaded in memory. This must be done before
- program headers are filled since they contain info about the layout.
- We do the following ordering: interp, symbol tables, relocations, progbits,
- nobits */
-static int sort_sections(TCCState *s1, int *sec_order, Section *interp)
-{
- Section *s;
- int i, j, k, f, f0, n;
- int nb_sections = s1->nb_sections;
- int *sec_cls = sec_order + nb_sections;
-
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_flags & SHF_ALLOC) {
- j = 0x100;
- if (s->sh_flags & SHF_WRITE)
- j = 0x200;
- if (s->sh_flags & SHF_TLS)
- j += 0x200;
- } else if (s->sh_name) {
- j = 0x700;
- } else {
- j = 0x900; /* no sh_name: won't go to file */
- }
- if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
- k = 0x10;
- } else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) {
- k = 0x11;
- if (i == nb_sections - 1) /* ".shstrtab" assumed to remain last */
- k = 0xff;
- } else if (s->sh_type == SHT_HASH) {
- k = 0x12;
- } else if (s->sh_type == SHT_RELX) {
- k = 0x20;
- if (s1->plt && s == s1->plt->reloc)
- k = 0x21;
- } else if (s->sh_type == SHT_PREINIT_ARRAY) {
- k = 0x41;
- } else if (s->sh_type == SHT_INIT_ARRAY) {
- k = 0x42;
- } else if (s->sh_type == SHT_FINI_ARRAY) {
- k = 0x43;
-#ifdef CONFIG_TCC_BCHECK
- } else if (s == bounds_section || s == lbounds_section) {
- k = 0x44;
-#endif
- } else if (s == rodata_section || 0 == strcmp(s->name,
".data.rel.ro")) {
- k = 0x45;
- } else if (s->sh_type == SHT_DYNAMIC) {
- k = 0x46;
- } else if (s == s1->got) {
- k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
- } else {
- k = 0x50;
- if (s->sh_type == SHT_NOTE)
- k = 0x60;
- if (s->sh_flags & SHF_EXECINSTR)
- k = 0x70;
- if (s->sh_type == SHT_NOBITS)
- k = 0x80;
- if (s == interp)
- k = 0x00;
- }
- k += j;
-
- for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n)
- sec_cls[n] = f, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
- }
- sec_order[0] = 0;
+/* Info for GNU_RELRO */
+struct ro_inf {
+ addr_t sh_offset;
+ addr_t sh_addr;
+ addr_t sh_size;
+};
- /* count PT_LOAD headers needed */
- n = f0 = 0;
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- k = sec_cls[i];
- f = 0;
- if (k < 0x700) {
- f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
- if ((k & 0xfff0) == 0x240) /* RELRO sections */
- f |= 1<<4;
- if (f != f0) /* start new header when flags changed or relro */
- f0 = f, ++n, f |= 1<<8;
- }
- sec_cls[i] = f;
- //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", !!f * n, i, f,
k, s->sh_type, s->sh_size, s->name);
- }
- return n;
-}
+static void alloc_sec_names(
+ TCCState *s1, int is_obj
+ );
-static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s)
-{
- if (s) {
- ph->p_offset = s->sh_offset;
- ph->p_vaddr = s->sh_addr;
- ph->p_filesz = s->sh_size;
- ph->p_align = s->sh_addralign;
- }
- ph->p_type = type;
- ph->p_flags = PF_R;
- ph->p_paddr = ph->p_vaddr;
- ph->p_memsz = ph->p_filesz;
- return ph;
-}
+static int layout_any_sections(
+ TCCState *s1, int file_offset, int *sec_order, int is_obj
+ );
/* Assign sections to segments and decide how are sections laid out when loaded
in memory. This function also fills corresponding program headers. */
-static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
+static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
+ int phnum, int phfill,
+ Section *interp,
+ struct ro_inf *roinf, int *sec_order)
{
+ int i, file_offset;
Section *s;
- addr_t addr, tmp, align, s_align, base;
- ElfW(Phdr) *ph = NULL;
- int i, f, n, phnum, phfill;
- int file_offset;
-
- /* compute number of program headers */
- phnum = sort_sections(s1, sec_order, d->interp);
- phfill = 0; /* set to 1 to have dll's with a PT_PHDR */
- if (d->interp)
- phfill = 2;
- phnum += phfill;
- if (d->note)
- ++phnum;
- if (d->dynamic)
- ++phnum;
- if (d->roinf)
- ++phnum;
- d->phnum = phnum;
- d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
file_offset = 0;
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
- s_align = ELF_PAGE_SIZE;
- if (s1->section_align)
- s_align = s1->section_align;
+ {
+ unsigned long s_align;
+ long long tmp;
+ addr_t addr;
+ ElfW(Phdr) *ph;
+ int j, k, f, file_type = s1->output_type;
- addr = ELF_START_ADDR;
- if (s1->output_type & TCC_OUTPUT_DYN)
- addr = 0;
+ s_align = ELF_PAGE_SIZE;
+ if (s1->section_align)
+ s_align = s1->section_align;
- if (s1->has_text_addr) {
- addr = s1->text_addr;
- if (0) {
+ if (s1->has_text_addr) {
int a_offset, p_offset;
+ addr = s1->text_addr;
/* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
ELF_PAGE_SIZE */
a_offset = (int) (addr & (s_align - 1));
@@ -2020,108 +1909,161 @@ static int layout_sections(TCCState *s1, int
*sec_order, struct dyn_inf *d)
if (a_offset < p_offset)
a_offset += s_align;
file_offset += (a_offset - p_offset);
+ } else {
+ if (file_type & TCC_OUTPUT_DYN)
+ addr = 0;
+ else
+ addr = ELF_START_ADDR;
+ /* compute address after headers */
+ addr += (file_offset & (s_align - 1));
}
- }
- base = addr;
- /* compute address after headers */
- addr = addr + (file_offset & (s_align - 1));
- n = 0;
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- f = sec_order[i + s1->nb_sections];
- align = s->sh_addralign - 1;
-
- if (f == 0) { /* no alloc */
- file_offset = (file_offset + align) & ~align;
- s->sh_offset = file_offset;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
- continue;
- }
+ ph = &phdr[0];
+ /* Leave one program headers for the program interpreter and one for
+ the program header table itself if needed. These are done later as
+ they require section layout to be done first. */
+ if (interp)
+ ph += 2;
- if ((f & 1<<8) && n) {
- /* different rwx section flags */
- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
- /* if in the middle of a page, w e duplicate the page in
- memory so that one copy is RX and the other is RW */
- if ((addr & (s_align - 1)) != 0)
- addr += s_align;
- } else {
- align = s_align - 1;
- }
- }
+ /* read only segment mapping for GNU_RELRO */
+ roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
- tmp = addr;
- addr = (addr + align) & ~align;
- file_offset += (int)(addr - tmp);
- s->sh_offset = file_offset;
- s->sh_addr = addr;
-
- if (f & 1<<8) {
- /* set new program header */
- ph = &d->phdr[phfill + n];
- ph->p_type = PT_LOAD;
- ph->p_align = s_align;
- ph->p_flags = PF_R;
- if (f & SHF_WRITE)
- ph->p_flags |= PF_W;
- if (f & SHF_EXECINSTR)
- ph->p_flags |= PF_X;
- if (f & SHF_TLS) {
- ph->p_type = PT_TLS;
- ph->p_align = 4;
+ for(j = 0; j < phfill; j++) {
+ ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
+ if (j == 0)
+ ph->p_flags = PF_R | PF_X;
+ else
+ ph->p_flags = PF_R | PF_W;
+ ph->p_align = j == 2 ? 4 : s_align;
+
+ /* Decide the layout of sections loaded in memory. This must
+ be done before program headers are filled since they contain
+ info about the layout. We do the following ordering: interp,
+ symbol tables, relocations, progbits, nobits */
+ /* XXX: do faster and simpler sorting */
+ f = -1;
+ for(k = 0; k < 10; k++) {
+ for(i = 1; i < s1->nb_sections; i++) {
+ s = s1->sections[i];
+ /* compute if section should be included */
+ if (j == 0) {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ SHF_ALLOC)
+ continue;
+ } else if (j == 1) {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ (SHF_ALLOC | SHF_WRITE))
+ continue;
+ } else {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS))
!=
+ (SHF_ALLOC | SHF_WRITE | SHF_TLS))
+ continue;
+ }
+ if (s == interp) {
+ if (k != 0)
+ continue;
+ } else if ((s->sh_type == SHT_DYNSYM ||
+ s->sh_type == SHT_STRTAB ||
+ s->sh_type == SHT_HASH)
+ && !strstr(s->name, ".stab")) {
+ if (k != 1)
+ continue;
+ } else if (s->sh_type == SHT_RELX) {
+ if (s1->plt && s == s1->plt->reloc) {
+ if (k != 3)
+ continue;
+ } else {
+ if (k != 2)
+ continue;
+ }
+ } else if ((s == rodata_section
+#ifdef CONFIG_TCC_BCHECK
+ || s == bounds_section
+ || s == lbounds_section
+#endif
+ ) && (s->sh_flags & SHF_WRITE)) {
+ if (k != 4)
+ continue;
+ /* Align next section on page size.
+ This is needed to remap roinf section ro. */
+ f = 1;
+
+ } else if (s->sh_type == SHT_PREINIT_ARRAY) {
+ if (k != 6)
+ continue;
+ } else if (s->sh_type == SHT_INIT_ARRAY) {
+ if (k != 7)
+ continue;
+ } else if (s->sh_type == SHT_FINI_ARRAY) {
+ if (k != 8)
+ continue;
+ } else if (s->sh_type == SHT_NOBITS) {
+ if (k != 9)
+ continue;
+ } else {
+ if (k != 5)
+ continue;
+ }
+ *sec_order++ = i;
+
+ /* section matches: we align it and add its size */
+ tmp = addr;
+ if (f-- == 0)
+ s->sh_addralign = PAGESIZE;
+ addr = (addr + s->sh_addralign - 1) &
+ ~(s->sh_addralign - 1);
+ file_offset += (int) ( addr - tmp );
+ s->sh_offset = file_offset;
+ s->sh_addr = addr;
+
+ /* update program header infos */
+ if (ph->p_offset == 0) {
+ ph->p_offset = file_offset;
+ ph->p_vaddr = addr;
+ ph->p_paddr = ph->p_vaddr;
+ }
+
+ if (k == 4) {
+ if (roinf->sh_size == 0) {
+ roinf->sh_offset = s->sh_offset;
+ roinf->sh_addr = s->sh_addr;
+ }
+ roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
+ }
+
+ addr += s->sh_size;
+ if (s->sh_type != SHT_NOBITS)
+ file_offset += s->sh_size;
+ }
}
- ph->p_offset = file_offset;
- ph->p_vaddr = addr;
- if (n == 0) {
+ if (j == 0) {
/* Make the first PT_LOAD segment include the program
headers itself (and the ELF header as well), it'll
come out with same memory use but will make various
tools like binutils strip work better. */
- ph->p_offset = 0;
- ph->p_vaddr = base;
- }
- ph->p_paddr = ph->p_vaddr;
- ++n;
- }
-
- if (f & 1<<4) {
- Section *roinf = &d->_roinf;
- if (roinf->sh_size == 0) {
- roinf->sh_offset = s->sh_offset;
- roinf->sh_addr = s->sh_addr;
- roinf->sh_addralign = 1;
+ ph->p_offset &= ~(ph->p_align - 1);
+ ph->p_vaddr &= ~(ph->p_align - 1);
+ ph->p_paddr &= ~(ph->p_align - 1);
}
- roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
+ ph->p_filesz = file_offset - ph->p_offset;
+ ph->p_memsz = addr - ph->p_vaddr;
+ ph++;
+ if (j == 0) {
+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
+ /* if in the middle of a page, we duplicate the page in
+ memory so that one copy is RX and the other is RW */
+ if ((addr & (s_align - 1)) != 0)
+ addr += s_align;
+ } else {
+ addr = (addr + s_align - 1) & ~(s_align - 1);
+ file_offset = (file_offset + s_align - 1) & ~(s_align - 1);
+ }
+ }
}
-
- addr += s->sh_size;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
-
- ph->p_filesz = file_offset - ph->p_offset;
- ph->p_memsz = addr - ph->p_vaddr;
- }
-
- /* Fill other headers */
- if (d->note)
- fill_phdr(++ph, PT_NOTE, d->note);
- if (d->dynamic)
- fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
- if (d->roinf)
- fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
- if (d->interp)
- fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
- if (phfill) {
- ph = &d->phdr[0];
- ph->p_offset = sizeof(ElfW(Ehdr));
- ph->p_vaddr = base + ph->p_offset;
- ph->p_filesz = phnum * sizeof(ElfW(Phdr));
- ph->p_align = 4;
- fill_phdr(ph, PT_PHDR, NULL);
}
- return file_offset;
+
+ /* all other sections come after */
+ return layout_any_sections(s1, file_offset, sec_order, 0);
}
/* put dynamic tag */
@@ -2133,6 +2075,75 @@ static void put_dt(Section *dynamic, int dt, addr_t val)
dyn->d_un.d_val = val;
}
+static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
+ Section *dynamic, Section *note, struct
ro_inf *roinf)
+{
+ ElfW(Phdr) *ph;
+
+ /* if interpreter, then add corresponding program header */
+ if (interp) {
+ ph = &phdr[0];
+
+ ph->p_type = PT_PHDR;
+ ph->p_offset = sizeof(ElfW(Ehdr));
+ ph->p_filesz = ph->p_memsz = phnum * sizeof(ElfW(Phdr));
+ ph->p_vaddr = interp->sh_addr - ph->p_filesz;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_flags = PF_R | PF_X;
+ ph->p_align = 4; /* interp->sh_addralign; */
+ ph++;
+
+ ph->p_type = PT_INTERP;
+ ph->p_offset = interp->sh_offset;
+ ph->p_vaddr = interp->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = interp->sh_size;
+ ph->p_memsz = interp->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = interp->sh_addralign;
+ }
+
+ if (note) {
+ ph = &phdr[phnum - 2 - (roinf != NULL)];
+
+ ph->p_type = PT_NOTE;
+ ph->p_offset = note->sh_offset;
+ ph->p_vaddr = note->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = note->sh_size;
+ ph->p_memsz = note->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = note->sh_addralign;
+ }
+
+ /* if dynamic section, then add corresponding program header */
+ if (dynamic) {
+ ph = &phdr[phnum - 1 - (roinf != NULL)];
+
+ ph->p_type = PT_DYNAMIC;
+ ph->p_offset = dynamic->sh_offset;
+ ph->p_vaddr = dynamic->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = dynamic->sh_size;
+ ph->p_memsz = dynamic->sh_size;
+ ph->p_flags = PF_R | PF_W;
+ ph->p_align = dynamic->sh_addralign;
+ }
+
+ if (roinf) {
+ ph = &phdr[phnum - 1];
+
+ ph->p_type = PT_GNU_RELRO;
+ ph->p_offset = roinf->sh_offset;
+ ph->p_vaddr = roinf->sh_addr;
+ ph->p_paddr = ph->p_vaddr;
+ ph->p_filesz = roinf->sh_size;
+ ph->p_memsz = roinf->sh_size;
+ ph->p_flags = PF_R;
+ ph->p_align = 1;
+ }
+}
+
/* Fill the dynamic section with tags describing the address and size of
sections */
static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
@@ -2234,7 +2245,6 @@ static void update_reloc_sections(TCCState *s1, struct
dyn_inf *dyninf)
}
}
-static int tidy_section_headers(TCCState *s1, int *sec_order);
#endif /* ndef ELF_OBJ_ONLY */
/* Create an ELF file on disk.
@@ -2256,9 +2266,6 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
ehdr.e_phentsize = sizeof(ElfW(Phdr));
ehdr.e_phnum = phnum;
ehdr.e_phoff = sizeof(ElfW(Ehdr));
-#ifndef ELF_OBJ_ONLY
- shnum = tidy_section_headers(s1, sec_order);
-#endif
}
/* align to 4 */
@@ -2321,8 +2328,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
sort_syms(s1, symtab_section);
- for(i = 1; i < shnum; i++) {
- s = s1->sections[sec_order ? sec_order[i] : i];
+ for(i = 1; i < s1->nb_sections; i++) {
+ s = s1->sections[sec_order[i]];
if (s->sh_type != SHT_NOBITS) {
while (offset < s->sh_offset) {
fputc(0, f);
@@ -2341,7 +2348,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int
phnum, ElfW(Phdr) *phdr,
offset++;
}
- for(i = 0; i < shnum; i++) {
+ for(i = 0; i < s1->nb_sections; i++) {
sh = &shdr;
memset(sh, 0, sizeof(ElfW(Shdr)));
s = s1->sections[i];
@@ -2422,7 +2429,7 @@ static int tcc_write_elf_file(TCCState *s1, const char
*filename, int phnum,
#ifndef ELF_OBJ_ONLY
/* Sort section headers by assigned sh_addr, remove sections
that we aren't going to output. */
-static int tidy_section_headers(TCCState *s1, int *sec_order)
+static void tidy_section_headers(TCCState *s1, int *sec_order)
{
int i, nnew, l, *backmap;
Section **snew, *s;
@@ -2462,8 +2469,8 @@ static int tidy_section_headers(TCCState *s1, int
*sec_order)
sec_order[i] = i;
tcc_free(s1->sections);
s1->sections = snew;
+ s1->nb_sections = nnew;
tcc_free(backmap);
- return nnew;
}
#ifdef TCC_TARGET_ARM
@@ -2529,33 +2536,34 @@ static void alloc_sec_names(TCCState *s1, int is_obj);
/* XXX: suppress unneeded sections */
static int elf_output_file(TCCState *s1, const char *filename)
{
- int i, ret, file_type, file_offset, *sec_order;
+ int i, ret, phnum, phfill, shnum, file_type, file_offset, *sec_order;
struct dyn_inf dyninf = {0};
- Section *interp, *dynstr, *dynamic;
+ struct ro_inf roinf;
+ ElfW(Phdr) *phdr;
+ Section *interp, *dynamic, *dynstr, *note;
+ struct ro_inf *roinf_use = NULL;
int textrel, got_sym, dt_flags_1;
file_type = s1->output_type;
s1->nb_errors = 0;
ret = -1;
- interp = dynstr = dynamic = NULL;
+ phdr = NULL;
sec_order = NULL;
- dyninf.roinf = &dyninf._roinf;
+ interp = dynamic = dynstr = note = NULL;
#ifdef TCC_TARGET_ARM
create_arm_attribute_section (s1);
#endif
#if TARGETOS_OpenBSD
- dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident",
"OpenBSD");
+ note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
#endif
#if TARGETOS_NetBSD
- dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
+ note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
#endif
-#if TARGETOS_FreeBSD || TARGETOS_NetBSD
- dyninf.roinf = NULL;
-#endif
+ {
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
tcc_add_runtime(s1);
resolve_common_syms(s1);
@@ -2572,7 +2580,6 @@ static int elf_output_file(TCCState *s1, const char
*filename)
interp->sh_addralign = 1;
ptr = section_ptr_add(interp, 1 + strlen(elfint));
strcpy(ptr, elfint);
- dyninf.interp = interp;
}
/* add dynamic symbol table */
@@ -2605,6 +2612,7 @@ static int elf_output_file(TCCState *s1, const char
*filename)
build_got_entries(s1, 0);
}
version_add (s1);
+ }
textrel = set_sec_sizes(s1);
alloc_sec_names(s1, 0);
@@ -2646,11 +2654,36 @@ static int elf_output_file(TCCState *s1, const char
*filename)
dynstr->sh_size = dynstr->data_offset;
}
+ /* compute number of program headers */
+ phfill = 2;
+ for (i = 1; i < s1->nb_sections; i++)
+ if (s1->sections[i]->sh_flags & SHF_TLS)
+ phfill = 3;
+ phnum = 3;
+ if (interp)
+ phnum += phfill;
+ if (note)
+ phnum++;
+#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD
+ /* GNU_RELRO */
+ phnum++, roinf_use = &roinf;
+#endif
+
+ /* allocate program segment headers */
+ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
+ /* compute number of sections */
+ shnum = s1->nb_sections;
/* this array is used to reorder sections in the output file */
- sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
+ sec_order = tcc_malloc(sizeof(int) * shnum);
+ sec_order[0] = 0;
+
/* compute section to program header mapping */
- file_offset = layout_sections(s1, sec_order, &dyninf);
+ file_offset = layout_sections(s1, phdr, phnum, phfill, interp, &roinf,
sec_order + 1);
+ /* Fill remaining program header and finalize relocation related to dynamic
+ linking. */
+ {
+ fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
if (dynamic) {
ElfW(Sym) *sym;
@@ -2672,6 +2705,7 @@ static int elf_output_file(TCCState *s1, const char
*filename)
/* if building executable or DLL, then relocate each section
except the GOT which is already relocated */
relocate_syms(s1, s1->symtab, 0);
+ ret = -1;
if (s1->nb_errors != 0)
goto the_end;
relocate_sections(s1);
@@ -2680,17 +2714,21 @@ static int elf_output_file(TCCState *s1, const char
*filename)
dynamic->data_offset = dyninf.data_offset;
fill_dynamic(s1, &dyninf);
}
+ tidy_section_headers(s1, sec_order);
+
/* Perform relocation to GOT or PLT entries */
if (file_type == TCC_OUTPUT_EXE && s1->static_link)
fill_got(s1);
else if (s1->got)
fill_local_got_entries(s1);
-
+ }
/* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr,
file_offset, sec_order);
+ ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset,
sec_order);
+ s1->nb_sections = shnum;
+
the_end:
tcc_free(sec_order);
- tcc_free(dyninf.phdr);
+ tcc_free(phdr);
return ret;
}
#endif /* ndef ELF_OBJ_ONLY */
@@ -2713,24 +2751,42 @@ static void alloc_sec_names(TCCState *s1, int is_obj)
strsec->sh_size = strsec->data_offset;
}
-/* Output an elf .o file */
-static int elf_output_obj(TCCState *s1, const char *filename)
+static int layout_any_sections(TCCState *s1, int file_offset, int *sec_order,
int is_obj)
{
+ int i;
Section *s;
- int i, ret, file_offset;
- s1->nb_errors = 0;
- /* Allocate strings for section names */
- alloc_sec_names(s1, 1);
- file_offset = sizeof (ElfW(Ehdr));
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
- file_offset = (file_offset + 15) & -16;
+ if (!is_obj && (s->sh_flags & SHF_ALLOC))
+ continue;
+ *sec_order++ = i;
+ file_offset = (file_offset + s->sh_addralign - 1) &
+ ~(s->sh_addralign - 1);
s->sh_offset = file_offset;
if (s->sh_type != SHT_NOBITS)
file_offset += s->sh_size;
}
+ return file_offset;
+}
+
+/* Output an elf .o file */
+static int elf_output_obj(TCCState *s1, const char *filename)
+{
+ int ret, file_offset;
+ int *sec_order;
+ s1->nb_errors = 0;
+
+ /* Allocate strings for section names */
+ alloc_sec_names(s1, 1);
+
+ /* this array is used to reorder sections in the output file */
+ sec_order = tcc_malloc(sizeof(int) * s1->nb_sections);
+ sec_order[0] = 0;
+ file_offset = layout_any_sections(s1, sizeof (ElfW(Ehdr)), sec_order + 1,
1);
+
/* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, NULL);
+ ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, sec_order);
+ tcc_free(sec_order);
return ret;
}
diff --git a/tccpe.c b/tccpe.c
index 0efe649..6677331 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -1071,18 +1071,12 @@ static int pe_section_class(Section *s)
{
int type, flags;
const char *name;
+
type = s->sh_type;
flags = s->sh_flags;
name = s->name;
- if (0 == memcmp(name, ".stab", 5)) {
- if (0 == s->s1->do_debug)
- return sec_last;
- return name[5] ? sec_stabstr : sec_stab;
- }
if (flags & SHF_ALLOC) {
- if (type == SHT_PROGBITS
- || type == SHT_INIT_ARRAY
- || type == SHT_FINI_ARRAY) {
+ if (type == SHT_PROGBITS) {
if (flags & SHF_EXECINSTR)
return sec_text;
if (flags & SHF_WRITE)
@@ -1095,44 +1089,52 @@ static int pe_section_class(Section *s)
return sec_pdata;
return sec_rdata;
} else if (type == SHT_NOBITS) {
- return sec_bss;
+ if (flags & SHF_WRITE)
+ return sec_bss;
}
- return sec_other;
} else {
if (0 == strcmp(name, ".reloc"))
return sec_reloc;
}
- return sec_last;
+ if (0 == memcmp(name, ".stab", 5))
+ return name[5] ? sec_stabstr : sec_stab;
+ if (flags & SHF_ALLOC)
+ return sec_other;
+ return -1;
}
static int pe_assign_addresses (struct pe_info *pe)
{
- int i, k, n, c, nbs;
+ int i, k, o, c;
DWORD addr;
- int *sec_order, *sec_cls;
+ int *section_order;
struct section_info *si;
Section *s;
TCCState *s1 = pe->s1;
if (PE_DLL == pe->type)
pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
- //pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
-
- nbs = s1->nb_sections;
- sec_order = tcc_mallocz(2 * sizeof (int) * nbs);
- sec_cls = sec_order + nbs;
- for (i = 1; i < nbs; ++i) {
- s = s1->sections[i];
- k = pe_section_class(s);
- for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n)
- sec_cls[n] = c, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
+ // pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
+
+ section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
+ for (o = k = 0 ; k < sec_last; ++k) {
+ for (i = 1; i < s1->nb_sections; ++i) {
+ s = s1->sections[i];
+ if (k == pe_section_class(s))
+ section_order[o++] = i;
+ }
}
+
si = NULL;
addr = pe->imagebase + 1;
- for (i = 1; (c = sec_cls[i]) < sec_last; ++i) {
- s = s1->sections[sec_order[i]];
+ for (i = 0; i < o; ++i) {
+ k = section_order[i];
+ s = s1->sections[k];
+ c = pe_section_class(s);
+
+ if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug)
+ continue;
if (PE_MERGE_DATA && c == sec_bss)
c = sec_data;
@@ -1193,31 +1195,28 @@ add_section:
}
//printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size,
si->pe_flags, s->name);
}
+ tcc_free(section_order);
#if 0
- for (i = 1; i < nbs; ++i) {
- Section *s = s1->sections[sec_order[i]];
+ for (i = 1; i < s1->nb_sections; ++i) {
+ Section *s = s1->sections[i];
int type = s->sh_type;
int flags = s->sh_flags;
printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
s->name,
type == SHT_PROGBITS ? "progbits" :
- type == SHT_INIT_ARRAY ? "initarr" :
- type == SHT_FINI_ARRAY ? "finiarr" :
type == SHT_NOBITS ? "nobits" :
type == SHT_SYMTAB ? "symtab" :
type == SHT_STRTAB ? "strtab" :
type == SHT_RELX ? "rel" : "???",
- (unsigned)s->sh_addr,
- (unsigned)s->data_offset,
+ s->sh_addr,
+ s->data_offset,
flags & SHF_ALLOC ? "alloc" : "",
flags & SHF_WRITE ? "write" : "",
flags & SHF_EXECINSTR ? "exec" : ""
);
- fflush(stdout);
}
s1->verbose = 2;
#endif
- tcc_free(sec_order);
return 0;
}
signature.asc
Description: Digital signature
_______________________________________________ Tinycc-devel mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/tinycc-devel
