Hi, I am working on the GSOC project "Bypass Assembler when generating LTO object files." So as a first step, I am adding .symtab along with __gnu_lto_slim symbol into it so that at a later stage, it can be recognized that this object file has been produced using -flto enabled. This patch is regarding the same. Although I am still testing this patch, I want general feedback on my code and design choice. I have extended simple_object_wrtie_struct to hold a list of symbols ( similar to sections ). A function in simple-object.c to add symbols. I am calling this function in lto-object.cc to add __gnu_lto_v1. Right now, as we are only working on ELF support first, I am adding .symtab in elf object files only.
Note:- I have added this patch on top of Jan's updated patch ( https://gcc.gnu.org/pipermail/gcc/2022-May/238670.html). I am pushing all these changes to my GitHub repo: https://github.com/rsh-raj/gcc/tree/patch-devel, so you can also view them from there. -Rishi --- >From 5760ccce2f4ae8930a07e3d0d4e0d029737a44d8 Mon Sep 17 00:00:00 2001 From: rsh-raj <rishiraj45...@gmail.com> Date: Mon, 19 Jun 2023 19:42:50 +0530 Subject: [PATCH] Added .symtab support --- gcc/lto-object.cc | 4 +- include/simple-object.h | 10 +++ libiberty/simple-object-common.h | 18 +++++ libiberty/simple-object-elf.c | 130 +++++++++++++++++++++++++++++-- libiberty/simple-object.c | 32 ++++++++ 5 files changed, 187 insertions(+), 7 deletions(-) diff --git a/gcc/lto-object.cc b/gcc/lto-object.cc index cb1c3a6cfb3..680977cb327 100644 --- a/gcc/lto-object.cc +++ b/gcc/lto-object.cc @@ -187,7 +187,9 @@ lto_obj_file_close (lto_file *file) int err; gcc_assert (lo->base.offset == 0); - + /*Add __gnu_lto_slim symbol*/ + if(flag_bypass_asm) + simple_object_write_add_symbol (lo->sobj_w, "__gnu_lto_slim",1,1); errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err); if (errmsg != NULL) { diff --git a/include/simple-object.h b/include/simple-object.h index 01f8a26f979..3a14184b12c 100644 --- a/include/simple-object.h +++ b/include/simple-object.h @@ -156,6 +156,11 @@ simple_object_start_write (simple_object_attributes *attrs, typedef struct simple_object_write_section_struct simple_object_write_section; +/* The type simple_object_symbol is a handle for a symbol + which is being written. */ + +typedef struct simple_object_symbol_struct simple_object_symbol; + /* Add a section to SIMPLE_OBJECT. NAME is the name of the new section. ALIGN is the required alignment expressed as the number of required low-order 0 bits (e.g., 2 for alignment to a 32-bit @@ -190,6 +195,11 @@ simple_object_write_add_data (simple_object_write *simple_object, extern const char * simple_object_write_to_file (simple_object_write *simple_object, int descriptor, int *err); +/*Add a symbol to sobj struct which will be written to common in simple_ +object_write_to_file function*/ +extern void +simple_object_write_add_symbol(simple_object_write *sobj, const char *name, +size_t size, unsigned int align); /* Release all resources associated with SIMPLE_OBJECT, including any simple_object_write_section's that may have been created. */ diff --git a/libiberty/simple-object-common.h b/libiberty/simple-object-common.h index b9d10550d88..df99c9d85ac 100644 --- a/libiberty/simple-object-common.h +++ b/libiberty/simple-object-common.h @@ -58,6 +58,24 @@ struct simple_object_write_struct simple_object_write_section *last_section; /* Private data for the object file format. */ void *data; + /*The start of the list of symbols.*/ + simple_object_symbol *symbols; + /*The last entry in the list of symbols*/ + simple_object_symbol *last_symbol; +}; + +/*A symbol in object file being created*/ +struct simple_object_symbol_struct +{ + /*Next in the list of symbols attached to an + simple_object_write*/ + simple_object_symbol *next; + /*The name of this symbol. */ + char *name; + /* Symbol value */ + unsigned int align; + /* Symbol size */ + size_t size; }; /* A section in an object file being created. */ diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index eee07039984..cbba88186bd 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -787,9 +787,9 @@ simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, ++shnum; if (shnum > 0) { - /* Add a section header for the dummy section and one for - .shstrtab. */ - shnum += 2; + /* Add a section header for the dummy section, + .shstrtab, .symtab and .strtab. */ + shnum += 4; } ehdr_size = (cl == ELFCLASS32 @@ -882,6 +882,51 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, errmsg, err); } +/* Write out an ELF Symbol*/ + +static int +simple_object_elf_write_symbol(simple_object_write *sobj, int descriptor, + off_t offset, unsigned int st_name, unsigned int st_value, size_t st_size, + unsigned char st_info, unsigned char st_other, unsigned int st_shndx, + const char **errmsg, int *err) +{ + struct simple_object_elf_attributes *attrs = + (struct simple_object_elf_attributes *) sobj->data; + const struct elf_type_functions* fns; + unsigned char cl; + size_t sym_size; + unsigned char buf[sizeof (Elf64_External_Shdr)]; + + fns = attrs->type_functions; + cl = attrs->ei_class; + + sym_size = (cl == ELFCLASS32 + ? sizeof (Elf32_External_Shdr) + : sizeof (Elf64_External_Shdr)); + memset (buf, 0, sizeof (Elf64_External_Shdr)); + + if(cl==ELFCLASS32) + { + ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name); + ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value); + ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size); + buf[4]=st_info; + buf[5]=st_other; + ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx); + } + else + { + ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name); + buf[4]=st_info; + buf[5]=st_other; + ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx); + ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value); + ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size); + } + return simple_object_internal_write(descriptor, offset,buf,sym_size, + errmsg,err); +} + /* Write out a complete ELF file. Ehdr initial dummy Shdr @@ -932,8 +977,8 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, if (shnum == 0) return NULL; - /* Add initial dummy Shdr and .shstrtab. */ - shnum += 2; + /* Add initial dummy Shdr, .shstrtab, .symtab and .strtab. */ + shnum += 4; shdr_offset = ehdr_size; sh_offset = shdr_offset + shnum * shdr_size; @@ -1036,6 +1081,70 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, sh_offset += sh_size; } + unsigned int num_sym=1; + simple_object_symbol *symbol; + + for(symbol=sobj->symbols;symbol!=NULL;symbol=symbol->next) + { + ++num_sym; + } + + size_t sym_size=cl==ELFCLASS32?sizeof(Elf32_External_Sym):sizeof(Elf64_External_Sym); + size_t sh_addralign=cl==ELFCLASS32?0x04:0x08; + size_t sh_entsize=sym_size; + size_t sh_size=num_sym*sym_size; + unsigned int sh_info=2; + if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, + sh_name, SHT_SYMTAB, 0, 0, sh_offset, + sh_size, shnum-2, sh_info, + sh_addralign,sh_entsize, &errmsg, err)) + return errmsg; + shdr_offset += shdr_size; + sh_name+=strlen(".symtab")+1; + /*Writes out the dummy symbol */ + + if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset, + 0,0,0,0,0,SHN_UNDEF,&errmsg,err)) + return errmsg; + sh_offset+=sym_size; + unsigned int st_name=1; + for(symbol=sobj->symbols;symbol!=NULL;symbol=symbol->next) + { + unsigned int st_value=1; + unsigned int st_size=1; + unsigned char st_info=17; + if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset, + st_name,st_value,st_size,st_info,0,SHN_COMMON,&errmsg,err)) + return errmsg; + sh_offset+=sym_size; + st_name+=strlen(symbol->name)+1; + + } + + if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, + sh_name, SHT_STRTAB, 0, 0, sh_offset, + st_name, 0, 0, + 1, 0, &errmsg, err)) + return errmsg; + shdr_offset += shdr_size; + sh_name+=strlen(".strtab")+1; + /*.strtab has a leading zero byte*/ + zero = 0; + if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1, + &errmsg, err)) + return errmsg; + ++sh_offset; + + for(symbol=sobj->symbols;symbol!=NULL;symbol=symbol->next) + { + size_t len=strlen(symbol->name)+1; + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) symbol->name, + len, &errmsg, err)) + return errmsg; + sh_offset += len; + + } if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, sh_name, SHT_STRTAB, 0, 0, sh_offset, sh_name + strlen (".shstrtab") + 1, 0, 0, @@ -1060,7 +1169,16 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, return errmsg; sh_offset += len; } - + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) ".symtab", + strlen (".symtab") + 1, &errmsg, err)) + return errmsg; + sh_offset+=strlen(".symtab")+1; + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) ".strtab", + strlen (".strtab") + 1, &errmsg, err)) + return errmsg; + sh_offset+=strlen(".strtab")+1; if (!simple_object_internal_write (descriptor, sh_offset, (const unsigned char *) ".shstrtab", strlen (".shstrtab") + 1, &errmsg, err)) diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c index 163e58a2f3b..73622160248 100644 --- a/libiberty/simple-object.c +++ b/libiberty/simple-object.c @@ -455,6 +455,8 @@ simple_object_start_write (simple_object_attributes *attrs, ret->sections = NULL; ret->last_section = NULL; ret->data = data; + ret->symbols=NULL; + ret->last_symbol=NULL; return ret; } @@ -538,6 +540,28 @@ simple_object_write_to_file (simple_object_write *sobj, int descriptor, { return sobj->functions->write_to_file (sobj, descriptor, err); } +/*Adds a symbol in to common*/ +void +simple_object_write_add_symbol(simple_object_write *sobj, const char *name, +size_t size, unsigned int align) +{ + simple_object_symbol *symbol; + symbol=XNEW(simple_object_symbol); + symbol->next=NULL; + symbol->name=xstrdup(name); + symbol->align=align; + symbol->size=size; + if(sobj->last_symbol==NULL) + { + sobj->symbols=symbol; + sobj->last_symbol=symbol; + } + else + { + sobj->last_symbol->next=symbol; + sobj->last_symbol=symbol; + } +} /* Release an simple_object_write. */ @@ -571,6 +595,14 @@ simple_object_release_write (simple_object_write *sobj) XDELETE (section); section = next_section; } + simple_object_symbol *symbol; + symbol=sobj->symbols; + while(symbol!=NULL) + { + free(symbol->name); + XDELETE(symbol); + symbol=symbol->next; + } sobj->functions->release_write (sobj->data); XDELETE (sobj); -- 2.40.1