fixed linker symbol generation - output format support
This commit is contained in:
parent
bb07bf31aa
commit
38e8a23025
1 changed files with 143 additions and 92 deletions
91
tccelf.c
91
tccelf.c
|
@ -955,8 +955,6 @@ static void add_init_array_defines(TCCState *s1, const char *section_name)
|
||||||
static void tcc_add_runtime(TCCState *s1)
|
static void tcc_add_runtime(TCCState *s1)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int i;
|
|
||||||
Section *s;
|
|
||||||
|
|
||||||
if (!s1->nostdlib) {
|
if (!s1->nostdlib) {
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
|
snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");
|
||||||
|
@ -1000,7 +998,17 @@ static void tcc_add_runtime(TCCState *s1)
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
|
if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {
|
||||||
tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
|
tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");
|
||||||
}
|
}
|
||||||
/* add various standard linker symbols */
|
}
|
||||||
|
|
||||||
|
/* add various standard linker symbols (must be done after the
|
||||||
|
sections are filled (for example after allocating common
|
||||||
|
symbols)) */
|
||||||
|
static void tcc_add_linker_symbols(TCCState *s1)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int i;
|
||||||
|
Section *s;
|
||||||
|
|
||||||
add_elf_sym(symtab_section,
|
add_elf_sym(symtab_section,
|
||||||
text_section->data_offset, 0,
|
text_section->data_offset, 0,
|
||||||
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),
|
||||||
|
@ -1059,6 +1067,28 @@ static char elf_interp[] = "/usr/libexec/ld-elf.so.1";
|
||||||
static char elf_interp[] = "/lib/ld-linux.so.2";
|
static char elf_interp[] = "/lib/ld-linux.so.2";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void tcc_output_binary(TCCState *s1, FILE *f,
|
||||||
|
const int *section_order)
|
||||||
|
{
|
||||||
|
Section *s;
|
||||||
|
int i, offset, size;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
for(i=1;i<s1->nb_sections;i++) {
|
||||||
|
s = s1->sections[section_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* output an ELF file */
|
/* output an ELF file */
|
||||||
/* XXX: suppress unneeded sections */
|
/* XXX: suppress unneeded sections */
|
||||||
int tcc_output_file(TCCState *s1, const char *filename)
|
int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
|
@ -1082,8 +1112,6 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
s1->nb_errors = 0;
|
s1->nb_errors = 0;
|
||||||
|
|
||||||
if (file_type != TCC_OUTPUT_OBJ) {
|
if (file_type != TCC_OUTPUT_OBJ) {
|
||||||
relocate_common_syms();
|
|
||||||
|
|
||||||
tcc_add_runtime(s1);
|
tcc_add_runtime(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1095,6 +1123,9 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
saved_dynamic_data_offset = 0; /* avoid warning */
|
saved_dynamic_data_offset = 0; /* avoid warning */
|
||||||
|
|
||||||
if (file_type != TCC_OUTPUT_OBJ) {
|
if (file_type != TCC_OUTPUT_OBJ) {
|
||||||
|
relocate_common_syms();
|
||||||
|
|
||||||
|
tcc_add_linker_symbols(s1);
|
||||||
|
|
||||||
if (!s1->static_link) {
|
if (!s1->static_link) {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -1310,7 +1341,11 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
/* allocate program segment headers */
|
/* allocate program segment headers */
|
||||||
phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
|
phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));
|
||||||
|
|
||||||
|
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||||
file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
|
file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
|
||||||
|
} else {
|
||||||
|
file_offset = 0;
|
||||||
|
}
|
||||||
if (phnum > 0) {
|
if (phnum > 0) {
|
||||||
/* compute section to program header mapping */
|
/* compute section to program header mapping */
|
||||||
if (s1->has_text_addr) {
|
if (s1->has_text_addr) {
|
||||||
|
@ -1413,10 +1448,18 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
ph->p_filesz = file_offset - ph->p_offset;
|
ph->p_filesz = file_offset - ph->p_offset;
|
||||||
ph->p_memsz = addr - ph->p_vaddr;
|
ph->p_memsz = addr - ph->p_vaddr;
|
||||||
ph++;
|
ph++;
|
||||||
|
if (j == 0) {
|
||||||
|
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||||
/* if in the middle of a page, we duplicate the page in
|
/* if in the middle of a page, we duplicate the page in
|
||||||
memory so that one copy is RX and the other is RW */
|
memory so that one copy is RX and the other is RW */
|
||||||
if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
|
if ((addr & (ELF_PAGE_SIZE - 1)) != 0)
|
||||||
addr += ELF_PAGE_SIZE;
|
addr += ELF_PAGE_SIZE;
|
||||||
|
} else {
|
||||||
|
addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);
|
||||||
|
file_offset = (file_offset + ELF_PAGE_SIZE - 1) &
|
||||||
|
~(ELF_PAGE_SIZE - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if interpreter, then add corresponing program header */
|
/* if interpreter, then add corresponing program header */
|
||||||
|
@ -1566,9 +1609,24 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
|
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* write elf file */
|
||||||
|
if (file_type == TCC_OUTPUT_OBJ)
|
||||||
|
mode = 0666;
|
||||||
|
else
|
||||||
|
mode = 0777;
|
||||||
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
error_noabort("could not write '%s'", filename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
f = fdopen(fd, "wb");
|
||||||
|
|
||||||
#ifdef TCC_TARGET_COFF
|
#ifdef TCC_TARGET_COFF
|
||||||
ret = tcc_output_coff(s1, filename);
|
if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
|
||||||
#else
|
tcc_output_coff(s1, f);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
|
||||||
sort_syms(s1, symtab_section);
|
sort_syms(s1, symtab_section);
|
||||||
|
|
||||||
/* align to 4 */
|
/* align to 4 */
|
||||||
|
@ -1608,20 +1666,10 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
ehdr.e_shnum = shnum;
|
ehdr.e_shnum = shnum;
|
||||||
ehdr.e_shstrndx = shnum - 1;
|
ehdr.e_shstrndx = shnum - 1;
|
||||||
|
|
||||||
/* write elf file */
|
|
||||||
if (file_type == TCC_OUTPUT_OBJ)
|
|
||||||
mode = 0666;
|
|
||||||
else
|
|
||||||
mode = 0777;
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
|
||||||
if (fd < 0) {
|
|
||||||
error_noabort("could not write '%s'", filename);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
f = fdopen(fd, "w");
|
|
||||||
fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
|
fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
|
||||||
fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
|
fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
|
||||||
offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
|
offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
|
||||||
|
|
||||||
for(i=1;i<s1->nb_sections;i++) {
|
for(i=1;i<s1->nb_sections;i++) {
|
||||||
s = s1->sections[section_order[i]];
|
s = s1->sections[section_order[i]];
|
||||||
if (s->sh_type != SHT_NOBITS) {
|
if (s->sh_type != SHT_NOBITS) {
|
||||||
|
@ -1634,12 +1682,13 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* output section headers */
|
||||||
while (offset < ehdr.e_shoff) {
|
while (offset < ehdr.e_shoff) {
|
||||||
fputc(0, f);
|
fputc(0, f);
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output section headers */
|
|
||||||
for(i=0;i<s1->nb_sections;i++) {
|
for(i=0;i<s1->nb_sections;i++) {
|
||||||
sh = &shdr;
|
sh = &shdr;
|
||||||
memset(sh, 0, sizeof(Elf32_Shdr));
|
memset(sh, 0, sizeof(Elf32_Shdr));
|
||||||
|
@ -1659,10 +1708,12 @@ int tcc_output_file(TCCState *s1, const char *filename)
|
||||||
}
|
}
|
||||||
fwrite(sh, 1, sizeof(Elf32_Shdr), f);
|
fwrite(sh, 1, sizeof(Elf32_Shdr), f);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tcc_output_binary(s1, f, section_order);
|
||||||
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
#endif
|
|
||||||
the_end:
|
the_end:
|
||||||
tcc_free(s1->symtab_to_dynsym);
|
tcc_free(s1->symtab_to_dynsym);
|
||||||
tcc_free(section_order);
|
tcc_free(section_order);
|
||||||
|
|
Loading…
Reference in a new issue