tccelf.c: factor out elf_output_obj()
The small common parts within elf_output_file() aren't worth the many #ifdefs. Also, set section sizes and allocate section names in 2 separate functions.
This commit is contained in:
parent
c74c6ed61a
commit
62c0c4c77a
4 changed files with 156 additions and 145 deletions
4
Makefile
4
Makefile
|
@ -62,10 +62,6 @@ else
|
||||||
endif
|
endif
|
||||||
export MACOSX_DEPLOYMENT_TARGET := 10.6
|
export MACOSX_DEPLOYMENT_TARGET := 10.6
|
||||||
endif
|
endif
|
||||||
# Unclear why the following ifdef was defined. Build fails on all *BSD
|
|
||||||
# ifdef CONFIG_BSD
|
|
||||||
# NATIVE_TARGET = $(ARCH)-$(TARGETOS)
|
|
||||||
# endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# run local version of tcc with local libraries and includes
|
# run local version of tcc with local libraries and includes
|
||||||
|
|
11
libtcc.c
11
libtcc.c
|
@ -1105,7 +1105,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
|
||||||
|
|
||||||
/* OpenBSD only has suffixed .so files; e.g., libc.so.96.0 */
|
/* OpenBSD only has suffixed .so files; e.g., libc.so.96.0 */
|
||||||
/* So we must process that */
|
/* So we must process that */
|
||||||
#if defined TARGETOS_OpenBSD
|
#if defined TARGETOS_OpenBSD && !defined _WIN32/* no dirent */
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
ST_FUNC char *tcc_openbsd_library_soversion(TCCState *s, const char *libraryname)
|
ST_FUNC char *tcc_openbsd_library_soversion(TCCState *s, const char *libraryname)
|
||||||
{
|
{
|
||||||
|
@ -1185,7 +1185,7 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
||||||
#elif defined TCC_TARGET_MACHO
|
#elif defined TCC_TARGET_MACHO
|
||||||
const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
|
const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
|
||||||
const char **pp = s->static_link ? libs + 1 : libs;
|
const char **pp = s->static_link ? libs + 1 : libs;
|
||||||
#elif defined TARGETOS_OpenBSD
|
#elif defined TARGETOS_OpenBSD && !defined _WIN32
|
||||||
const char *libs[] = { s->static_link
|
const char *libs[] = { s->static_link
|
||||||
? NULL
|
? NULL
|
||||||
/* find exact versionned .so.x.y name as no
|
/* find exact versionned .so.x.y name as no
|
||||||
|
@ -1479,11 +1479,8 @@ static int tcc_set_linker(TCCState *s, const char *option)
|
||||||
s->filetype |= AFF_WHOLE_ARCHIVE;
|
s->filetype |= AFF_WHOLE_ARCHIVE;
|
||||||
else
|
else
|
||||||
s->filetype &= ~AFF_WHOLE_ARCHIVE;
|
s->filetype &= ~AFF_WHOLE_ARCHIVE;
|
||||||
} else if (ret = link_option(option, "z=", &p), ret) {
|
} else if (link_option(option, "z=", &p)) {
|
||||||
if (!strcmp(p, "notext"))
|
ignoring = 1;
|
||||||
; /* ignore */
|
|
||||||
else
|
|
||||||
goto err;
|
|
||||||
} else if (p) {
|
} else if (p) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
284
tccelf.c
284
tccelf.c
|
@ -1071,11 +1071,6 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count) {
|
|
||||||
/* allocate the section */
|
|
||||||
sr->sh_flags |= SHF_ALLOC;
|
|
||||||
sr->sh_size = count * sizeof(ElfW_Rel);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -1566,29 +1561,8 @@ ST_FUNC void resolve_common_syms(TCCState *s1)
|
||||||
tcc_add_linker_symbols(s1);
|
tcc_add_linker_symbols(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcc_output_binary(TCCState *s1, FILE *f,
|
|
||||||
const int *sec_order)
|
|
||||||
{
|
|
||||||
Section *s;
|
|
||||||
int i, offset, size;
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
for(i=1;i<s1->nb_sections;i++) {
|
|
||||||
s = s1->sections[sec_order[i]];
|
|
||||||
if (s->sh_type != SHT_NOBITS &&
|
|
||||||
(s->sh_flags & SHF_ALLOC)) {
|
|
||||||
while (offset < s->sh_offset) {
|
|
||||||
fputc(0, f);
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
size = s->sh_size;
|
|
||||||
fwrite(s->data, 1, size, f);
|
|
||||||
offset += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
|
|
||||||
ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
|
ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
|
||||||
{
|
{
|
||||||
int sym_index = ELFW(R_SYM) (rel->r_info);
|
int sym_index = ELFW(R_SYM) (rel->r_info);
|
||||||
|
@ -1791,43 +1765,40 @@ static void export_global_syms(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Allocate strings for section names and decide if an unallocated section
|
/* decide if an unallocated section should be output. */
|
||||||
should be output.
|
static int set_sec_sizes(TCCState *s1)
|
||||||
NOTE: the strsec section comes last, so its size is also correct ! */
|
|
||||||
static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Section *s;
|
Section *s;
|
||||||
int textrel = 0;
|
int textrel = 0;
|
||||||
|
int file_type = s1->output_type;
|
||||||
|
|
||||||
/* Allocate strings for section names */
|
/* Allocate strings for section names */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
/* when generating a DLL, we include relocations but we may
|
if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
|
||||||
patch them */
|
/* when generating a DLL, we include relocations but
|
||||||
#ifndef ELF_OBJ_ONLY
|
we may patch them */
|
||||||
if (file_type == TCC_OUTPUT_DLL &&
|
if (file_type == TCC_OUTPUT_DLL
|
||||||
s->sh_type == SHT_RELX &&
|
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
|
||||||
!(s->sh_flags & SHF_ALLOC) &&
|
int count = prepare_dynamic_rel(s1, s);
|
||||||
(s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) &&
|
if (count) {
|
||||||
prepare_dynamic_rel(s1, s)) {
|
/* allocate the section */
|
||||||
if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
|
s->sh_flags |= SHF_ALLOC;
|
||||||
textrel = 1;
|
s->sh_size = count * sizeof(ElfW_Rel);
|
||||||
} else
|
if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
|
||||||
#endif
|
textrel = 1;
|
||||||
if ((s1->do_debug && s->sh_type != SHT_RELX) ||
|
}
|
||||||
file_type == TCC_OUTPUT_OBJ ||
|
}
|
||||||
(s->sh_flags & SHF_ALLOC) ||
|
} else if ((s->sh_flags & SHF_ALLOC)
|
||||||
i == (s1->nb_sections - 1)
|
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
|| s->sh_type == SHT_ARM_ATTRIBUTES
|
|| s->sh_type == SHT_ARM_ATTRIBUTES
|
||||||
#endif
|
#endif
|
||||||
) {
|
|| s1->do_debug) {
|
||||||
/* we output all sections if debug or object file */
|
|
||||||
s->sh_size = s->data_offset;
|
s->sh_size = s->data_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
/* XXX: Suppress stack unwinding section. */
|
/* XXX: Suppress stack unwinding section. */
|
||||||
if (s->sh_type == SHT_ARM_EXIDX) {
|
if (s->sh_type == SHT_ARM_EXIDX) {
|
||||||
|
@ -1835,13 +1806,12 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
|
||||||
s->sh_size = 0;
|
s->sh_size = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (s->sh_size || (s->sh_flags & SHF_ALLOC))
|
|
||||||
s->sh_name = put_elf_str(strsec, s->name);
|
|
||||||
}
|
}
|
||||||
strsec->sh_size = strsec->data_offset;
|
|
||||||
return textrel;
|
return textrel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Info to be copied in dynamic section */
|
/* Info to be copied in dynamic section */
|
||||||
struct dyn_inf {
|
struct dyn_inf {
|
||||||
Section *dynamic;
|
Section *dynamic;
|
||||||
|
@ -1858,23 +1828,29 @@ struct ro_inf {
|
||||||
addr_t sh_size;
|
addr_t sh_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void alloc_sec_names(
|
||||||
|
TCCState *s1, int is_obj
|
||||||
|
);
|
||||||
|
|
||||||
|
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
|
/* Assign sections to segments and decide how are sections laid out when loaded
|
||||||
in memory. This function also fills corresponding program headers. */
|
in memory. This function also fills corresponding program headers. */
|
||||||
static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
int phnum, int phfill,
|
int phnum, int phfill,
|
||||||
Section *interp, Section* strsec,
|
Section *interp,
|
||||||
struct ro_inf *roinf, int *sec_order)
|
struct ro_inf *roinf, int *sec_order)
|
||||||
{
|
{
|
||||||
int i, sh_order_index, file_offset;
|
int i, file_offset;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
|
||||||
sh_order_index = 1;
|
|
||||||
file_offset = 0;
|
file_offset = 0;
|
||||||
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
|
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
|
||||||
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
{
|
||||||
if (phnum > 0) { /* phnum is 0 for TCC_OUTPUT_OBJ */
|
|
||||||
unsigned long s_align;
|
unsigned long s_align;
|
||||||
long long tmp;
|
long long tmp;
|
||||||
addr_t addr;
|
addr_t addr;
|
||||||
|
@ -1979,7 +1955,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
if (k != 5)
|
if (k != 5)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sec_order[sh_order_index++] = i;
|
*sec_order++ = i;
|
||||||
|
|
||||||
/* section matches: we align it and add its size */
|
/* section matches: we align it and add its size */
|
||||||
tmp = addr;
|
tmp = addr;
|
||||||
|
@ -2039,26 +2015,11 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ELF_OBJ_ONLY */
|
|
||||||
|
|
||||||
/* all other sections come after */
|
/* all other sections come after */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
return layout_any_sections(s1, file_offset, sec_order, 0);
|
||||||
s = s1->sections[i];
|
|
||||||
if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
|
|
||||||
continue;
|
|
||||||
sec_order[sh_order_index++] = 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
/* put dynamic tag */
|
/* put dynamic tag */
|
||||||
static void put_dt(Section *dynamic, int dt, addr_t val)
|
static void put_dt(Section *dynamic, int dt, addr_t val)
|
||||||
{
|
{
|
||||||
|
@ -2269,7 +2230,8 @@ static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif /* ndef ELF_OBJ_ONLY */
|
||||||
|
|
||||||
/* Create an ELF file on disk.
|
/* Create an ELF file on disk.
|
||||||
This function handle ELF specific layout requirements */
|
This function handle ELF specific layout requirements */
|
||||||
|
@ -2390,6 +2352,28 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcc_output_binary(TCCState *s1, FILE *f,
|
||||||
|
const int *sec_order)
|
||||||
|
{
|
||||||
|
Section *s;
|
||||||
|
int i, offset, size;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
for(i=1;i<s1->nb_sections;i++) {
|
||||||
|
s = s1->sections[sec_order[i]];
|
||||||
|
if (s->sh_type != SHT_NOBITS &&
|
||||||
|
(s->sh_flags & SHF_ALLOC)) {
|
||||||
|
while (offset < s->sh_offset) {
|
||||||
|
fputc(0, f);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
size = s->sh_size;
|
||||||
|
fwrite(s->data, 1, size, f);
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Write an elf, coff or "binary" file */
|
/* Write an elf, coff or "binary" file */
|
||||||
static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
|
static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
|
||||||
ElfW(Phdr) *phdr, int file_offset, int *sec_order)
|
ElfW(Phdr) *phdr, int file_offset, int *sec_order)
|
||||||
|
@ -2472,7 +2456,6 @@ static void tidy_section_headers(TCCState *s1, int *sec_order)
|
||||||
s1->nb_sections = nnew;
|
s1->nb_sections = nnew;
|
||||||
tcc_free(backmap);
|
tcc_free(backmap);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
#ifdef TCC_TARGET_ARM
|
||||||
static void create_arm_attribute_section(TCCState *s1)
|
static void create_arm_attribute_section(TCCState *s1)
|
||||||
|
@ -2539,33 +2522,30 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
struct dyn_inf dyninf = {0};
|
struct dyn_inf dyninf = {0};
|
||||||
struct ro_inf roinf;
|
struct ro_inf roinf;
|
||||||
ElfW(Phdr) *phdr;
|
ElfW(Phdr) *phdr;
|
||||||
Section *strsec, *interp, *dynamic, *dynstr, *note = NULL;
|
Section *interp, *dynamic, *dynstr, *note;
|
||||||
//#ifndef ELF_OBJ_ONLY
|
|
||||||
struct ro_inf *roinf_use = NULL;
|
struct ro_inf *roinf_use = NULL;
|
||||||
//#endif
|
int textrel;
|
||||||
|
|
||||||
file_type = s1->output_type;
|
file_type = s1->output_type;
|
||||||
|
|
||||||
#ifdef TCC_TARGET_ARM
|
|
||||||
create_arm_attribute_section (s1);
|
|
||||||
#endif
|
|
||||||
#if TARGETOS_OpenBSD
|
|
||||||
if (file_type != TCC_OUTPUT_OBJ)
|
|
||||||
note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
|
|
||||||
#endif
|
|
||||||
#if TARGETOS_NetBSD
|
|
||||||
if (file_type != TCC_OUTPUT_OBJ)
|
|
||||||
note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
phdr = NULL;
|
phdr = NULL;
|
||||||
sec_order = NULL;
|
sec_order = NULL;
|
||||||
interp = dynamic = dynstr = NULL; /* avoid warning */
|
interp = dynamic = dynstr = note = NULL;
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifdef TCC_TARGET_ARM
|
||||||
if (file_type != TCC_OUTPUT_OBJ) {
|
create_arm_attribute_section (s1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARGETOS_OpenBSD
|
||||||
|
note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARGETOS_NetBSD
|
||||||
|
note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
/* if linking, also link in runtime libraries (libc, libgcc, etc.) */
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
resolve_common_syms(s1);
|
resolve_common_syms(s1);
|
||||||
|
@ -2612,17 +2592,11 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
build_got_entries(s1);
|
build_got_entries(s1);
|
||||||
version_add (s1);
|
version_add (s1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* we add a section for symbols */
|
textrel = set_sec_sizes(s1);
|
||||||
strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
|
alloc_sec_names(s1, 0);
|
||||||
put_elf_str(strsec, "");
|
|
||||||
|
|
||||||
/* Allocate strings for section names */
|
if (!s1->static_link) {
|
||||||
ret = alloc_sec_names(s1, file_type, strsec);
|
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
if (dynamic) {
|
|
||||||
int i;
|
int i;
|
||||||
/* add a list of needed dlls */
|
/* add a list of needed dlls */
|
||||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||||
|
@ -2640,7 +2614,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
|
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
|
||||||
/* XXX: currently, since we do not handle PIC code, we
|
/* XXX: currently, since we do not handle PIC code, we
|
||||||
must relocate the readonly segments */
|
must relocate the readonly segments */
|
||||||
if (ret)
|
if (textrel)
|
||||||
put_dt(dynamic, DT_TEXTREL, 0);
|
put_dt(dynamic, DT_TEXTREL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2655,16 +2629,13 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
dynamic->sh_size = dynamic->data_offset;
|
dynamic->sh_size = dynamic->data_offset;
|
||||||
dynstr->sh_size = dynstr->data_offset;
|
dynstr->sh_size = dynstr->data_offset;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 1; i < s1->nb_sections &&
|
for (i = 1; i < s1->nb_sections &&
|
||||||
!(s1->sections[i]->sh_flags & SHF_TLS); i++);
|
!(s1->sections[i]->sh_flags & SHF_TLS); i++);
|
||||||
phfill = 2 + (i < s1->nb_sections);
|
phfill = 2 + (i < s1->nb_sections);
|
||||||
|
|
||||||
/* compute number of program headers */
|
/* compute number of program headers */
|
||||||
if (file_type == TCC_OUTPUT_OBJ)
|
if (file_type == TCC_OUTPUT_DLL)
|
||||||
phnum = phfill = 0;
|
|
||||||
else if (file_type == TCC_OUTPUT_DLL)
|
|
||||||
phnum = 3;
|
phnum = 3;
|
||||||
else if (s1->static_link)
|
else if (s1->static_link)
|
||||||
phnum = 3;
|
phnum = 3;
|
||||||
|
@ -2673,31 +2644,25 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
phnum += note != NULL;
|
phnum += note != NULL;
|
||||||
|
#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD
|
||||||
#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD && !defined(__APPLE__) && !defined(_WIN32)
|
|
||||||
/* GNU_RELRO */
|
/* GNU_RELRO */
|
||||||
if (file_type != TCC_OUTPUT_OBJ)
|
phnum++, roinf_use = &roinf;
|
||||||
phnum++, roinf_use = &roinf;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* allocate program segment headers */
|
/* allocate program segment headers */
|
||||||
phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
|
phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
|
||||||
|
|
||||||
/* compute number of sections */
|
/* compute number of sections */
|
||||||
shnum = s1->nb_sections;
|
shnum = s1->nb_sections;
|
||||||
|
|
||||||
/* this array is used to reorder sections in the output file */
|
/* this array is used to reorder sections in the output file */
|
||||||
sec_order = tcc_malloc(sizeof(int) * shnum);
|
sec_order = tcc_malloc(sizeof(int) * shnum);
|
||||||
sec_order[0] = 0;
|
sec_order[0] = 0;
|
||||||
|
|
||||||
/* compute section to program header mapping */
|
/* compute section to program header mapping */
|
||||||
file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec,
|
file_offset = layout_sections(s1, phdr, phnum, phfill, interp, &roinf, sec_order + 1);
|
||||||
&roinf, sec_order);
|
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
|
||||||
/* Fill remaining program header and finalize relocation related to dynamic
|
/* Fill remaining program header and finalize relocation related to dynamic
|
||||||
linking. */
|
linking. */
|
||||||
if (file_type != TCC_OUTPUT_OBJ) {
|
{
|
||||||
fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
|
fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
|
@ -2735,32 +2700,85 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
else if (s1->got)
|
else if (s1->got)
|
||||||
fill_local_got_entries(s1);
|
fill_local_got_entries(s1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Create the ELF file with name 'filename' */
|
/* Create the ELF file with name 'filename' */
|
||||||
ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
|
ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
|
||||||
s1->nb_sections = shnum;
|
s1->nb_sections = shnum;
|
||||||
goto the_end;
|
|
||||||
the_end:
|
the_end:
|
||||||
tcc_free(sec_order);
|
tcc_free(sec_order);
|
||||||
tcc_free(phdr);
|
tcc_free(phdr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif /* ndef ELF_OBJ_ONLY */
|
||||||
|
|
||||||
|
/* Allocate strings for section names */
|
||||||
|
static void alloc_sec_names(TCCState *s1, int is_obj)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Section *s, *strsec;
|
||||||
|
|
||||||
|
strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
|
||||||
|
put_elf_str(strsec, "");
|
||||||
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
|
s = s1->sections[i];
|
||||||
|
if (is_obj)
|
||||||
|
s->sh_size = s->data_offset;
|
||||||
|
if (s->sh_size || (s->sh_flags & SHF_ALLOC))
|
||||||
|
s->sh_name = put_elf_str(strsec, s->name);
|
||||||
|
}
|
||||||
|
strsec->sh_size = strsec->data_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int layout_any_sections(TCCState *s1, int file_offset, int *sec_order, int is_obj)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Section *s;
|
||||||
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
|
s = s1->sections[i];
|
||||||
|
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, sec_order);
|
||||||
|
tcc_free(sec_order);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
|
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
|
||||||
{
|
{
|
||||||
int ret;
|
if (s->output_type == TCC_OUTPUT_OBJ)
|
||||||
|
return elf_output_obj(s, filename);
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
if (s->output_type != TCC_OUTPUT_OBJ) {
|
return pe_output_file(s, filename);
|
||||||
ret = pe_output_file(s, filename);
|
|
||||||
} else
|
|
||||||
#elif TCC_TARGET_MACHO
|
#elif TCC_TARGET_MACHO
|
||||||
if (s->output_type != TCC_OUTPUT_OBJ) {
|
return macho_output_file(s, filename);
|
||||||
ret = macho_output_file(s, filename);
|
#else
|
||||||
} else
|
return elf_output_file(s, filename);
|
||||||
#endif
|
#endif
|
||||||
ret = elf_output_file(s, filename);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
|
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ ifeq ($(ARCH),arm)
|
||||||
# of functions via bit masking comes out as 1. Just disable thumb.
|
# of functions via bit masking comes out as 1. Just disable thumb.
|
||||||
test.ref: CFLAGS+=-marm
|
test.ref: CFLAGS+=-marm
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH),i386)
|
ifeq ($(ARCH)$(CONFIG_WIN32),i386)
|
||||||
# tcctest.c:get_asm_string uses a construct that is checked too strictly
|
# tcctest.c:get_asm_string uses a construct that is checked too strictly
|
||||||
# by GCC in 32bit mode when PIC is enabled.
|
# by GCC in 32bit mode when PIC is enabled.
|
||||||
test.ref: CFLAGS+=-fno-PIC -fno-PIE -Wl,-z,notext
|
test.ref: CFLAGS+=-fno-PIC -fno-PIE -Wl,-z,notext
|
||||||
|
|
Loading…
Reference in a new issue