#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# optionalsym.c
# Makefile
# optionalsym64.c
# optionalsym.h
# optionalsym64.h
# This archive created: Wed Feb 16 10:47:23 2000
export PATH; PATH=/bin:$PATH
if test -f 'optionalsym.c'
then
echo shar: will not over-write existing file "'optionalsym.c'"
else
sed 's/^X//' << \SHAR_EOF > 'optionalsym.c'
X
X/*
X This program both reports on and sets
X the st_other field in symbols.
X It focuses on the STO_OPTIONAL flag of the st_other field.
X
X
X Usage:
X optionalsym [-v <selectname>]
X [-p]
X [-u <updateto>]
X [-y symname [ -y symname]]
X file ...
X
X If -u supplied, selected symbols have their
X st_other field updated to contain the -u value.
X For example:
X -u STO_OPTIONAL
X Legal values for the <updateto>
X are STO_DEFAULT STO_INTERNAL STO_HIDDEN
X STO_PROTECTED STO_OPTIONAL
X If multiple -u are supplied the last is actually used.
X
X
X If -p supplied, selected symbols are printed
X (if -u also suppled, the symbol
X is printed before updating)
X If -u is not supplied, -p is assumed.
X
X -v <selectname>
X selects symbols with st_other having that value.
X optionalsymbol -v STO_OPTIONAL -p t.o
X prints all symbols marked STO_OPTIONAL.
X The <selectname> may be any of the STO* mentioned above.
X If multiple -v are supplied the last is actually used.
X
X -y symname
X selects a symbol with the name "symname".
X If multiple -y options are given each name in
X the set of names is selected.
X
X If both -u and -y are given, symbols must have
X BOTH the <selectname> and any one of the
X symbol names to be selected.
X
X
XWritten March 1997 by David B. Anderson Silicon Graphics.
X [email protected]
X
XFor general distribution to anyone who is interested.
X
XIt's a hack :-)
X
X*/
X
X
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <a.out.h>
X#include <malloc.h>
X#include <alloca.h>
X#include <string.h>
X#include <time.h>
X#include "optionalsym.h"
X#include <elf_abi.h>
X#include <elf_mips.h>
X#include <elf.h>
X#include "optionalsym64.h"
X
X
X#define USHORT unsigned short
Xstatic void dofile(char *);
Xstatic void do_elf_file(char *);
Xstatic void elf_get_section_table_strings(unsigned long,
X unsigned long, unsigned long, unsigned long);
Xstatic char * get_dynstr_string(unsigned long offset, int index);
Xstatic void elf_get_symstrings(unsigned long offset,
X unsigned long entsize,unsigned long count ,
X unsigned stringsecnum);
Xstatic void elf_ck_dynsym(unsigned long offset,unsigned
X long size, int symstr_index);
Xstatic int get_symtab_section(unsigned long offset,
X unsigned long entsize,
X unsigned long count);
X
Xint symbol_header_printed;
X
X
Xstatic void add_desired_symbol(char *name);
X
X
Xchar *Usage =
X"Usage: optionalsym -v <selectname> -p -u <updateto> -y <symname> file ...";
X
X#define P printf
X#define F fflush(stdout)
X#define RR(buf,loc,siz) ((fseek(fin,loc,0)<0) ? -1 : \
X ((fread(buf,siz,1,fin)!=1)?-2:0))
X#define RN(buf,siz) ((fread(buf,siz,1,fin) != 1) ? -2 : 0)
X#define CURLOC ( ftell(fin) )
X#define SEEKTO(i) (fseek(fin,i,SEEK_SET))
X
X
Xstatic struct filehdr fhdr;
X
Xstatic Elf32_Ehdr ehdr;
X
Xchar *filename;
X
X
Xstatic char *elf_shstrings_data; /* section name strings */
Xstatic long elf_shstrings_length;
X /* length of currentsection. Might be zero..*/
X
Xstatic long elf_shstrings_max; /* size of malloc-d space */
X
Xstatic char *dynamic_sect_strings;
Xstatic long dynamic_sect_strings_length;
Xstatic int dynamic_sect_strings_sect_index;
X
Xstruct a_desired_symbol *ds_array;
Xlong ds_next_to_use;
X /* ds_next_to_use is the count of the number of names
X supplied with -y flags
X */
Xlong ds_allocated_count;
X /* ds_allocated_count is the number of structs
X malloc-d
X */
X
X/* the -v value, as a name and an integer.
X name 0 unless -v supplied.
X*/
Xint value_search;
Xchar *value_search_name;
X
X/* The -u value, as a name and an integer.
X Name 0 unless -u supplied.
X*/
Xint new_value;
Xchar * new_value_name;
X
Xint printsymbols;
Xstatic int saw_dash_p;
X
XFILE *fin;
X
Xstruct sto_xlate_s
X{
X char *sx_name;
X int sx_val;
X} sto_xlate_data[] = {
X{"STO_DEFAULT",STO_DEFAULT},
X{"STO_INTERNAL",STO_INTERNAL},
X{"STO_HIDDEN",STO_HIDDEN},
X{"STO_PROTECTED",STO_PROTECTED},
X{"STO_OPTIONAL",STO_OPTIONAL},
X{0,0}
X};
X
Xstatic int
Xst_other_to_int(char *option,char *name)
X{
X int i;
X for( i = 0 ; sto_xlate_data[i].sx_name; ++i) {
X if(streq(sto_xlate_data[i].sx_name,name)) {
X return sto_xlate_data[i].sx_val;
X }
X }
X fprintf(stderr," \"%s\" not valid in \"%s %s\"\n",
X name,option,name);
X exit(1);
X /*NOTREACHED*/
X}
X
Xint
Xmain(int argc,char **argv)
X{
X int i;
X int turn_off_options = 0;
X
X if( argc == 1) {
X printf("%s\n",Usage);
X exit(1);
X } else {
X argv++;
X for(i =1;turn_off_options == 0 && i<argc; i++,argv++) {
X if(strcmp(argv[0],"--") == 0) {
X turn_off_options = 1;
X continue;
X }
X if(strcmp(argv[0],"-p") == 0) {
X printsymbols = 1;
X saw_dash_p = 1;
X continue;
X }
X if(strcmp(argv[0],"-v") == 0) {
X i++;
X argv++;
X if(i >= argc) {
X fprintf(stderr,
X "-v cannot be the last option!\n");
X exit(1);
X
X }
X value_search_name = argv[0];
X value_search = st_other_to_int("-v",
X value_search_name);
X continue;
X }
X if(strcmp(argv[0],"-u") == 0) {
X i++;
X argv++;
X if(i >= argc) {
X fprintf(stderr,
X "-u cannot be the last option!\n");
X exit(1);
X
X }
X new_value_name = argv[0];
X new_value = st_other_to_int("-u",
X new_value_name);
X
X continue;
X }
X if(strcmp(argv[0],"-y") == 0) {
X i++;
X argv++;
X if(i >= argc) {
X fprintf(stderr,
X "-y cannot be the last option!\n");
X exit(1);
X
X }
X add_desired_symbol(argv[0]);
X
X continue;
X }
X /* The rest must be file names */
X break;
X }
X
X /* print if -p or if not updating.
X */
X if(saw_dash_p) {
X printsymbols=1;
X } else if (!new_value_name) {
X printsymbols=1;
X }
X for( ; i<argc; i++,argv++) {
X char *opentype = "r";
X if(new_value_name)
X opentype = "r+b";
X fin = fopen(argv[0],opentype);
X if(fin == NULL) {
X printf(
X "No such file as %s or cannot open read-only\n",
X argv[0]);
X continue;
X }
X filename = argv[0];
X printf("%s:\n",filename);
X dofile(argv[0]);
X fclose(fin);
X }
X }
X return 0;
X}
X
X#define MIPSEBMAGIC_2 0x0163
X
Xstatic void
Xdofile(char *s)
X{
X int res;
X
X res = RR(&fhdr,0,sizeof(fhdr));
X if(res) {
X P("could not read whole file header of %s\n",
X filename);
X return;
X }
X memcpy((void *)&ehdr,(void *)&fhdr,sizeof(ehdr));
X if(IS_ELF(ehdr)) {
X do_elf_file(s);
X return;
X }
X P("We don't do COFF files\n");
X F;
X}
X
Xstatic void
Xdo_elf_file(char *s)
X{
X int res;
X unsigned char c;
X
X SEEKTO(0);
X res = RR(&ehdr,0,sizeof(ehdr));
X if(res) {
X P("could not read whole ELF file header of %s\n",
X filename);
X return;
X }
X c = ehdr.e_ident[EI_CLASS];
X#ifdef HAS_ELFHDR64
X if (c == ELFCLASS64) {
X do_elf_file64(s);
X return;
X }
X#endif
X
X elf_get_section_table_strings(ehdr.e_shoff,
X ehdr.e_shentsize,ehdr.e_shnum,ehdr.e_shstrndx);
X if(elf_shstrings_data == 0) {
X return;
X }
X
X get_symtab_section(ehdr.e_shoff,ehdr.e_shentsize,ehdr.e_shnum);
X
X
X return;
X}
X
X#define SHTYPESTRING(x) get_shtypestring(x)
X#define SHSTRING(x) ((elf_shstrings_length > (x)) ? \
X (x) + elf_shstrings_data : \
X "Invalid sh_name value")
X/*
X*/
Xstatic void
Xelf_get_symstrings(unsigned long offset,
X unsigned long entsize,unsigned long count,
X unsigned stringsecnum )
X{
X int i;
X Elf32_Shdr *psh;
X Elf32_Shdr *orig_psh;
X long curloc;
X unsigned long seekres;
X int res;
X
X
X if(entsize < sizeof(Elf32_Shdr)) {
X P("Elf Section header too small? %ld vs %ld\n",
X entsize,(unsigned long)sizeof(Elf32_Shdr));
X }
X if(offset == 0) {
X P("No section headers\n");
X return;
X }
X curloc = CURLOC;
X if(curloc < 0) {
X P("\tcurrent loc unknown/error in ftell?????\n");
X return;
X }
X i =SEEKTO(offset);
X if(i) {
X P("Seek to %ld to read section headers failed\n",offset);
X return;
X }
X psh = (Elf32_Shdr *)alloca(count * entsize);
X if(psh == 0) {
X P("malloc to %ld bytes of section header space failed\n",
X count *entsize);
X return;
X }
X orig_psh = psh;
X i = RN(orig_psh,count*entsize);
X if(i) {
X P("Read %lu bytes of section headers failed\n",
X count*entsize);
X return;
X }
X
X
X i = stringsecnum;
X psh = (Elf32_Shdr *)((char *)psh + (entsize*stringsecnum));
X dynamic_sect_strings_sect_index = i;
X dynamic_sect_strings_length = psh->sh_size;
X if(dynamic_sect_strings) {
X free(dynamic_sect_strings);
X }
X dynamic_sect_strings = malloc(dynamic_sect_strings_length);
X res = RR(dynamic_sect_strings,psh->sh_offset,
X dynamic_sect_strings_length);
X if(res) {
X P("Could not read section %ld strings at %llx\n",
X (long)stringsecnum,
X (long long)psh->sh_offset);
X dynamic_sect_strings = 0;
X dynamic_sect_strings_length = 0;
X dynamic_sect_strings_sect_index = 0;
X seekres =SEEKTO(curloc);
X if(seekres) {
X P("Seek back to %ld after reading sect headers failed\n",
X curloc);
X }
X return;
X }
X i =SEEKTO(curloc);
X if(i) {
X P("Seek to %ld after reading sect headers failed\n",offset);
X return;
X }
X}
Xstatic char *
Xget_dynstr_string(unsigned long offset, int index)
X{
X char *retval;
X
X
X if(index != dynamic_sect_strings_sect_index) {
X
X P("link is %d, sect found was %d\n",
X (int)index,
X (int)dynamic_sect_strings_sect_index);
X retval ="dynamic section link does not match"
X " section of dynamic strings";
X return retval;
X }
X if(offset >= dynamic_sect_strings_length) {
X return "offset beyond end of dynamic sect strings";
X }
X return dynamic_sect_strings + offset;
X}
X
Xstatic void
Xelf_get_section_table_strings(unsigned long offset,
X unsigned long entsize,
X unsigned long count,
X unsigned long stringsection)
X{
X int i;
X Elf32_Shdr *psh;
X Elf32_Shdr *orig_psh;
X
X
X if(count == 0) {
X P("No section headers\n");
X return;
X }
X elf_shstrings_length = 0;
X if(entsize < sizeof(Elf32_Shdr)) {
X P("Elf Section header too small? %ld vs %ld\n",
X entsize,(unsigned long)sizeof(Elf32_Shdr));
X }
X
X i =SEEKTO(offset + entsize*stringsection);
X if(i) {
X P("Seek to %ld to read string section header failed\n",
X offset+
X entsize*stringsection);
X return;
X }
X psh = (Elf32_Shdr *)malloc( entsize);
X if(psh == 0) {
X P("malloc to %ld bytes of section header space failed\n",
X entsize);
X return;
X }
X orig_psh = psh;
X i = RN(psh,entsize);
X if(i) {
X P("read string section header failed\n");
X return;
X }
X if(psh->sh_type == SHT_NULL) {
X P("String section type SHT_NULL!!. No sstring section!\n");
X return;
X }
X i =SEEKTO(psh->sh_offset);
X if(i) {
X P("Seek to %ld string section data failed\n",
X psh->sh_offset);
X elf_shstrings_length = 0;
X return;
X }
X if(psh->sh_size > elf_shstrings_max) {
X if(elf_shstrings_data)
X free(elf_shstrings_data);
X elf_shstrings_data = (char *)malloc(psh->sh_size);
X elf_shstrings_max = psh->sh_size;
X if(elf_shstrings_data == 0) {
X elf_shstrings_max = 0;
X P("Unable to malloc %ld bytes of string space!\n",
X (long)psh->sh_size);
X return;
X }
X }
X elf_shstrings_length = psh->sh_size;
X i = RN(elf_shstrings_data,psh->sh_size);
X if(i) {
X P("Read %ld bytes of string section string data failed\n",
X elf_shstrings_length);
X elf_shstrings_length = 0;
X return;
X }
X free(orig_psh);
X}
X
X
Xstatic int
Xget_symtab_section(unsigned long offset,
X unsigned long entsize,unsigned long count)
X{
X
X int i;
X Elf32_Shdr *psh;
X Elf32_Shdr *orig_psh;
X char *namestr;
X
X
X if(entsize < sizeof(Elf32_Shdr)) {
X P("Elf Section header too small? %ld vs %ld\n",
X entsize,(unsigned long)sizeof(Elf32_Shdr));
X return 0;
X }
X if(count == 0) {
X P("No section headers\n");
X return 0;
X }
X i =SEEKTO(offset);
X if(i) {
X P("Seek to %ld to read section headers failed\n",offset);
X return 0;
X }
X psh = (Elf32_Shdr *)malloc(count * entsize);
X if(psh == 0) {
X P("malloc to %ld bytes of section header space failed\n",
X count *entsize);
X return 0;
X }
X orig_psh = psh;
X i = RN(orig_psh,count*entsize);
X if(i) {
X P("Read %lu bytes of section headers failed\n",
X count*entsize);
X return 0;
X }
X
X for(i = 0; i < count;
X i++, psh = (Elf32_Shdr *) ((char *)psh + entsize)) {
X namestr = SHSTRING(psh->sh_name);
X if( 0 == strcmp(namestr,".dynsym")) {
X symbol_header_printed = 0;
X elf_get_symstrings(ehdr.e_shoff,ehdr.e_shentsize,
X ehdr.e_shnum,
X psh->sh_link);
X elf_ck_dynsym(psh->sh_offset,psh->sh_size,psh->sh_link);
X continue;
X }
X if( 0 == strcmp(namestr,".symtab")) {
X symbol_header_printed = 0;
X elf_get_symstrings(ehdr.e_shoff,ehdr.e_shentsize,
X ehdr.e_shnum,
X psh->sh_link);
X elf_ck_dynsym(psh->sh_offset,psh->sh_size,psh->sh_link);
X continue;
X }
X }
X free(orig_psh);
X return 0;
X}
X
Xvoid
Xprint_a_symbol(unsigned int nameindex,
X unsigned long long value,
X unsigned long long size,
X unsigned char info,
X unsigned char other,
X unsigned short shndx,
X char * symname)
X{
X if(!symbol_header_printed) {
X P("nameindx :value :size :info bind type :other :sectindex :name\n");
X symbol_header_printed = 1;
X }
X P("%6d ",nameindex);
X P(":0x%-8llx ",(unsigned long long)value);
X P(":0x%-4llx ",(unsigned long long)size);
X P(":0x%02x ",info);
X P("0x%02x ",ELF64_ST_BIND(info));
X if(ELF64_ST_BIND(info) == STB_LOCAL) {
X P("STB_LOCAL ");
X } else if(ELF64_ST_BIND(info) == STB_GLOBAL) {
X P("STB_GLOBAL ");
X } else if(ELF64_ST_BIND(info) == STB_WEAK) {
X P("STB_WEAK ");
X }
X P("0x%02x ",ELF64_ST_TYPE(info));
X if(ELF64_ST_TYPE(info) == STT_NOTYPE) {
X P("STT_NOTYPE ");
X } else if(ELF64_ST_TYPE(info) == STT_OBJECT) {
X P("STT_OBJECT ");
X } else if(ELF64_ST_TYPE(info) == STT_FUNC) {
X P("STT_FUNC ");
X } else if(ELF64_ST_TYPE(info) == STT_SECTION) {
X P("STT_SECTION ");
X } else if(ELF64_ST_TYPE(info) == STT_FILE) {
X P("STT_FILE ");
X }
X P(":0x%02x ",other);
X if(other == STO_DEFAULT)
X P("STO_DEFAULT ");
X if(other == STO_INTERNAL)
X P("STO_INTERNAL ");
X if(other == STO_HIDDEN)
X P("STO_HIDDEN ");
X if(other == STO_PROTECTED)
X P("STO_PROTECTED ");
X if(other == STO_OPTIONAL)
X P("STO_OPTIONAL ");
X P(":%-4d ",shndx);
X if(shndx == SHN_UNDEF) {
X P("SHN_UNDEF ");
X }
X if(shndx == SHN_ABS) {
X P("SHN_ABS ");
X }
X if(shndx == SHN_COMMON) {
X P("SHN_COMMON ");
X }
X if(shndx == SHN_MIPS_ACOMMON) {
X P("SHN_MIPS_ACOMMON ");
X }
X if(shndx == SHN_MIPS_TEXT) {
X P("SHN_MIPS_TEXT ");
X }
X if(shndx == SHN_MIPS_DATA) {
X P("SHN_MIPS_DATA ");
X }
X if(shndx == SHN_MIPS_SCOMMON) {
X P("SHN_MIPS_SCOMMON ");
X }
X if(shndx == SHN_MIPS_SUNDEFINED) {
X P("SHN_MIPS_SUNDEFINED ");
X }
X P(":%s",symname);
X P("\n");
X}
X
X/*
X Handle one symbol.
X*/
X/*ARGSUSED*/
Xstatic void
Xhandle_one_symbol(Elf32_Sym *symp,long symindx,
X int symstr_index,long *modify_count)
X{
X char *symname;
X
X symname = get_dynstr_string(symp->st_name,symstr_index);
X
X if(value_search_name) {
X if (value_search != symp->st_other) {
X return;
X }
X if(ds_next_to_use > 0) {
X if(!interesting_name(symname)) {
X return;
X }
X }
X } else {
X if(ds_next_to_use > 0) {
X if(!interesting_name(symname)) {
X return;
X }
X } else {
X /* nothing asked for! */
X return;
X }
X }
X
X /* we have not discarded the entry so do something with/to it
X */
X if(printsymbols) {
X print_a_symbol(symp->st_name,
X symp->st_value,
X symp->st_size,
X symp->st_info,
X symp->st_other,
X symp->st_shndx,
X symname);
X }
X if(new_value_name) {
X symp->st_other = new_value;
X *modify_count += 1;
X }
X
X}
Xstatic void
Xelf_ck_dynsym(unsigned long offset,unsigned
X long size, int symstr_index)
X
X{
X long ecount = 0;
X unsigned long size2 = 0;
X unsigned long i;
X Elf32_Sym *origbuffer;
X Elf32_Sym *buffer;
X int res;
X long modify_count = 0;
X
X ecount = size/sizeof(Elf32_Sym);
X size2 = ecount * sizeof(Elf32_Sym);
X if(size != size2) {
X P("Bogus size of symbols. %lu not divisible by %lu\n",
X size,(unsigned long)sizeof(Elf32_Sym));
X return ;
X }
X
X buffer = alloca(size);
X
X res = RR(buffer,offset,size);
X if(res) {
X P("could not read whole symbol section of %s "
X "at offset %lu size %lu\n",
X filename,
X offset,size);
X return ;
X }
X origbuffer = buffer;
X
X
X for(i = 0; i < ecount; ++i,++buffer) {
X handle_one_symbol(buffer,i,symstr_index,&modify_count);
X }
X if(modify_count > 0) {
X size_t res;
X res =SEEKTO(offset);
X if(res) {
X P("Seek to %ld to prepare write section failed\n",
X offset);
X return;
X }
X res =fwrite(origbuffer,size,1,fin);
X if(res != 1) {
X P("Unable to write back section: fwrite returned %d\n",res);
X return;
X }
X fflush(fin);
X }
X
X
X return ;
X}
X
Xstatic void
Xadd_desired_symbol(char *name)
X{
X if(ds_array == 0) {
X ds_allocated_count = DS_INITIAL_ALLOC;
X ds_array = malloc(sizeof(struct a_desired_symbol)*
X ds_allocated_count);
X if(ds_array == 0) {
X fprintf(stderr,
X "Unable to malloc %ld bytes for desired symbol array\n",
X (long)sizeof(struct a_desired_symbol)*
X ds_allocated_count);
X exit(1);
X }
X }
X if(ds_next_to_use >= ds_allocated_count) {
X struct a_desired_symbol * ds_arrayl;
X ds_allocated_count += DS_ADDITIONAL_ALLOC;
X ds_arrayl = realloc(ds_array,sizeof(struct a_desired_symbol)*
X ds_allocated_count);
X if(ds_arrayl == 0) {
X fprintf(stderr,
X "Unable to realloc %ld bytes for desired symbol array\n",
X (long)sizeof(struct a_desired_symbol)*
X ds_allocated_count);
X exit(1);
X }
X ds_array = ds_arrayl;
X }
X ds_array[ds_next_to_use].ds_name = name;
X ++ds_next_to_use;
X}
X
X
X/*
XReturn 1 if the name is in the list of names as -y options.
XReturn 0 otherwise.
X*/
Xint
Xinteresting_name(char *name)
X{
X long i;
X
X for (i = 0; i < ds_next_to_use; ++i) {
X if(streq(ds_array[i].ds_name,name)) {
X return 1;
X }
X }
X return 0;
X
X}
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XSHELL = /bin/sh
X
X
X# Add -fullwarn for full checking
XCFLAGS = -g -DHAS_ELFHDR64
X
Xall: optionalsym
Xshar:
X shar -p X optionalsym.c Makefile optionalsym64.c \
X optionalsym.h optionalsym64.h \
X >/d2/public/optionalsym.shar
X
X
Xoptionalsym: optionalsym.o optionalsym64.o
X $(CC) $(CFLAGS) -g optionalsym.o optionalsym64.o -o optionalsym
Xclobber:
X -rm *.o
X -rm optionalsym
X -rm core a.out
X
SHAR_EOF
fi # end of overwriting check
if test -f 'optionalsym64.c'
then
echo shar: will not over-write existing file "'optionalsym64.c'"
else
sed 's/^X//' << \SHAR_EOF > 'optionalsym64.c'
X
X/*
X optionalsym64.c
X
X For handling 64-bit elf objects.
X
X*/
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <a.out.h>
X#include <malloc.h>
X#include <string.h>
X#include <alloca.h>
X#include "optionalsym.h"
X#ifdef HAS_ELFHDR64
X#include <elf_abi.h>
X#include <elf_mips.h>
X#endif
X#include <elf.h>
X#include "optionalsym64.h"
X
X
X#define USHORT unsigned short
X
X#define P printf
X#define F fflush(stdout)
X#define RR(buf,loc,siz) ((fseek(fin,loc,0)<0) ? -1 : \
X ((fread(buf,siz,1,fin)!=1)?-2:0))
X#define RN(buf,siz) ((fread(buf,siz,1,fin) != 1) ? -2 : 0)
X#define CURLOC ( ftell(fin) )
X#define SEEKTO(i) (fseek(fin,i,SEEK_SET))
X
Xtypedef unsigned long long ULONG64;
Xtypedef long long LONG64;
X
Xstatic void elf_get_section_table_strings(ULONG64 offset,
X ULONG64 entsize,ULONG64 count,ULONG64 stringsection);
Xstatic char * get_dynstr_string(ULONG64 offset, int index);
Xstatic void elf_get_symstrings(ULONG64 offset, ULONG64 entsize, ULONG64 count,
X unsigned sec_strings_index);
Xstatic void elf_ck_dynsym64(unsigned long offset,unsigned
X long size, int symstr_index);
Xstatic int get_symtab_section(unsigned long offset,
X unsigned long entsize,unsigned long count);
X
X
X#ifdef HAS_ELFHDR64
Xstatic Elf64_Ehdr ehdr;
Xstatic void handle_one_symbol(Elf64_Sym *symp,long symindx,
X int symstr_index,long *modify_count);
X#endif
X
X
X
Xstatic char *elf_shstrings_data; /* section name strings */
Xstatic long elf_shstrings_length; /* length of currentsection. Might be zero..*/
Xstatic long elf_shstrings_max; /* size of malloc-d space */
Xstatic char *dynamic_sect_strings;
Xstatic long dynamic_sect_strings_length;
Xstatic int dynamic_sect_strings_sect_index;
X
X
X
X#ifdef HAS_ELFHDR64
Xvoid
Xdo_elf_file64(char *s)
X{
X int res;
X
X SEEKTO(0);
X res = RR(&ehdr,0,sizeof(ehdr));
X if(res) {
X P("could not read whole ELF file header of %s\n",filename);
X return;
X }
X elf_get_section_table_strings(ehdr.e_shoff,
X ehdr.e_shentsize,ehdr.e_shnum,ehdr.e_shstrndx);
X if(elf_shstrings_data == 0) {
X return;
X }
X get_symtab_section(ehdr.e_shoff,ehdr.e_shentsize,ehdr.e_shnum);
X}
X
X
Xstatic void
Xelf_get_section_table_strings(ULONG64 offset,ULONG64 entsize,
X ULONG64 count,ULONG64 stringsection)
X{
X int i;
X Elf64_Shdr *psh;
X Elf64_Shdr *orig_psh;
X
X
X if(count == 0) {
X P("No section headers\n");
X return;
X }
X elf_shstrings_length = 0;
X if(entsize < (ULONG64)sizeof(Elf64_Shdr)) {
X P("Elf Section header too small? %lld vs %lld\n",
X (ULONG64)entsize,(ULONG64)sizeof(Elf64_Shdr));
X }
X
X i =SEEKTO(offset + entsize*stringsection);
X if(i) {
X P("Seek to %lld to read string section header failed\n",
X (ULONG64)offset+
X (ULONG64)entsize*stringsection);
X return;
X }
X psh = (Elf64_Shdr *)malloc( entsize);
X if(psh == 0) {
X P("malloc to %lld bytes of section header space failed\n"
X ,(LONG64)entsize);
X return;
X }
X orig_psh = psh;
X i = RN(psh,entsize);
X if(i) {
X P("read string section header failed\n");
X return;
X }
X if(psh->sh_type == SHT_NULL) {
X P("String section type SHT_NULL!!. No string section!\n");
X return;
X }
X i =SEEKTO(psh->sh_offset);
X if(i) {
X P("Seek to %llu string section data failed\n",(ULONG64)psh->sh_offset);
X elf_shstrings_length = 0;
X return;
X }
X if(psh->sh_size > elf_shstrings_max) {
X if(elf_shstrings_data)
X free(elf_shstrings_data);
X elf_shstrings_data = (char *)malloc(psh->sh_size);
X elf_shstrings_max = psh->sh_size;
X if(elf_shstrings_data == 0) {
X elf_shstrings_max = 0;
X P("Unable to malloc %ld bytes of string space!\n",
X (long)psh->sh_size);
X return;
X }
X
X }
X elf_shstrings_length = psh->sh_size;
X i = RN(elf_shstrings_data,psh->sh_size);
X if(i) {
X P("Read %llu bytes of string section string data failed\n",
X (ULONG64)elf_shstrings_length);
X elf_shstrings_length = 0;
X return;
X }
X free(orig_psh);
X}
X
X#define SHSTRING(x) ((elf_shstrings_length > (x)) ? \
X (x) + elf_shstrings_data : \
X "Invalid sh_name value")
Xstatic void
Xelf_get_symstrings(ULONG64 offset, ULONG64 entsize, ULONG64 count,
X unsigned stringsecnum)
X{
X int i;
X Elf64_Shdr *psh;
X Elf64_Shdr *orig_psh;
X long curloc;
X ULONG64 seekres;
X int res;
X
X
X if(entsize < sizeof(Elf64_Shdr)) {
X P("Elf Section header too small? %ld vs %ld\n",
X (long)entsize,(long)sizeof(Elf64_Shdr));
X }
X if(count == 0) {
X P("No section headers\n");
X return;
X }
X curloc = CURLOC;
X if(curloc < 0) {
X P("\tcurrent loc unknown/error error in ftell?\n");
X return;
X }
X i =SEEKTO(offset);
X if(i) {
X P("Seek to %ld to read section headers failed\n",
X (long)offset);
X return;
X }
X psh = (Elf64_Shdr *)alloca(count * entsize);
X if(psh == 0) {
X P("malloc to %ld bytes of section header space failed\n",
X (long)(count *entsize));
X return;
X }
X orig_psh = psh;
X i = RN(orig_psh,count*entsize);
X if(i) {
X P("Read %lu bytes of section headers failed\n",
X (unsigned long)(count*entsize));
X return;
X }
X i = stringsecnum;
X psh = (Elf64_Shdr *)((char *)psh + (entsize*stringsecnum));
X dynamic_sect_strings_sect_index = i;
X dynamic_sect_strings_length = psh->sh_size;
X if(dynamic_sect_strings) {
X free(dynamic_sect_strings);
X }
X dynamic_sect_strings = malloc(dynamic_sect_strings_length);
X res = RR(dynamic_sect_strings,psh->sh_offset,
X dynamic_sect_strings_length);
X if(res) {
X P("Could not read section %ld strings at %llx\n",
X (long)stringsecnum,
X (long long)psh->sh_offset);
X dynamic_sect_strings = 0;
X dynamic_sect_strings_length = 0;
X dynamic_sect_strings_sect_index = 0;
X seekres =SEEKTO(curloc);
X if(seekres) {
X P("Seek back to %ld after reading sect headers failed\n",
X (long)curloc);
X }
X return;
X }
X i =SEEKTO(curloc);
X if(i) {
X P("Seek to %ld after reading sect headers failed\n",
X (long)offset);
X return;
X }
X
X
X}
Xstatic char *
Xget_dynstr_string(ULONG64 offset, int index)
X{
X
X
X if(index != dynamic_sect_strings_sect_index) {
X P("link is %d, sect found was %d\n",
X (int)index,
X (int)dynamic_sect_strings_sect_index);
X return"dynamic section link does not match section of dynamic strings";
X }
X if(offset >= dynamic_sect_strings_length) {
X return "offset beyond end of dynamic sect strings";
X }
X return dynamic_sect_strings + offset;
X}
X
X
X
X
Xstatic int
Xget_symtab_section(unsigned long offset,unsigned long entsize,unsigned long count)
X{
X
X int i;
X Elf64_Shdr *psh;
X Elf64_Shdr *orig_psh;
X char *namestr;
X
X
X if(entsize < sizeof(Elf64_Shdr)) {
X P("Elf Section header too small? %ld vs %ld\n",
X entsize,(unsigned long)sizeof(Elf64_Shdr));
X return 0;
X }
X if(count == 0) {
X P("No section headers\n");
X return 0;
X }
X i =SEEKTO(offset);
X if(i) {
X P("Seek to %ld to read section headers failed\n",offset);
X return 0;
X }
X psh = (Elf64_Shdr *)malloc(count * entsize);
X if(psh == 0) {
X P("malloc to %ld bytes of section header space failed\n",count *entsize);
X return 0;
X }
X orig_psh = psh;
X i = RN(orig_psh,count*entsize);
X if(i) {
X P("Read %lu bytes of section headers failed\n",count*entsize);
X return 0;
X }
X
X for(i = 0; i < count;
X i++, psh = (Elf64_Shdr *) ((char *)psh + entsize)) {
X namestr = SHSTRING(psh->sh_name);
X if( 0 == strcmp(namestr,".dynsym")) {
X elf_get_symstrings(ehdr.e_shoff,ehdr.e_shentsize,
X ehdr.e_shnum,
X psh->sh_link);
X elf_ck_dynsym64(psh->sh_offset,psh->sh_size,psh->sh_link);
X continue;
X }
X if( 0 == strcmp(namestr,".symtab")) {
X elf_get_symstrings(ehdr.e_shoff,ehdr.e_shentsize,
X ehdr.e_shnum,
X psh->sh_link);
X elf_ck_dynsym64(psh->sh_offset,psh->sh_size,psh->sh_link);
X continue;
X }
X }
X free(orig_psh);
X return 0;
X}
X
Xstatic void
Xelf_ck_dynsym64(unsigned long offset,unsigned
X long size, int symstr_index)
X
X{
X long ecount = 0;
X unsigned long size2 = 0;
X unsigned long i;
X Elf64_Sym *origbuffer;
X Elf64_Sym *buffer;
X int res;
X long modify_count = 0;
X
X ecount = size/sizeof(Elf64_Sym);
X size2 = ecount * sizeof(Elf64_Sym);
X if(size != size2) {
X P("Bogus size of symbols. %lu not divisible by %lu\n",
X size,(unsigned long)sizeof(Elf64_Sym));
X return ;
X }
X
X buffer = alloca(size);
X
X res = RR(buffer,offset,size);
X if(res) {
X P("could not read whole dynsym section of %s "
X "at offset %lu size %lu\n",
X filename,
X offset,size);
X return ;
X }
X origbuffer = buffer;
X
X for(i = 0; i < ecount; ++i,++buffer) {
X handle_one_symbol(buffer,i,symstr_index,&modify_count);
X }
X if(modify_count > 0) {
X size_t res;
X res =SEEKTO(offset);
X if(res) {
X P("Seek to %ld to prepare write section failed\n",
X offset);
X return;
X }
X res =fwrite(origbuffer,size,1,fin);
X if(res != 1) {
X P("Unable to write back section: fwrite returned %d\n",res);
X return;
X }
X fflush(fin);
X }
X
X
X return;
X}
X
X/*
X Handle one symbol.
X*/
X/*ARGSUSED*/
Xstatic void
Xhandle_one_symbol(Elf64_Sym *symp,long symindx,
X int symstr_index,long *modify_count)
X{
X char *symname;
X
X symname = get_dynstr_string(symp->st_name,symstr_index);
X
X if(value_search_name) {
X if (value_search != symp->st_other) {
X return;
X }
X if(ds_next_to_use > 0) {
X if(!interesting_name(symname)) {
X return;
X }
X }
X } else {
X if(ds_next_to_use > 0) {
X if(!interesting_name(symname)) {
X return;
X }
X } else {
X /* nothing asked for! */
X return;
X }
X }
X
X /* we have not discarded the entry so do something with/to it
X */
X if(printsymbols) {
X print_a_symbol(symp->st_name,
X symp->st_value,
X symp->st_size,
X symp->st_info,
X symp->st_other,
X symp->st_shndx,
X symname);
X }
X if(new_value_name) {
X symp->st_other = new_value;
X *modify_count += 1;
X }
X
X}
X#endif /* HAS_ELFHDR64 */
SHAR_EOF
fi # end of overwriting check
if test -f 'optionalsym.h'
then
echo shar: will not over-write existing file "'optionalsym.h'"
else
sed 's/^X//' << \SHAR_EOF > 'optionalsym.h'
X/*
X
X optionalsym.h
X
X*/
Xextern char *filename;
Xextern FILE *fin;
Xextern char *getshstring(long long sectype);
Xextern int printsymbols;
Xextern void print_a_symbol(unsigned int nameindex,
X unsigned long long value,
X unsigned long long size,
X unsigned char info,
X unsigned char other,
X unsigned short shndx,
X char * symname);
Xint interesting_name(char *name);
X#define streq(_a,_b) (strcmp(_a,_b) == 0)
X
X/* the following is mostly for the
X -ya -yb etc
X list of symbols-to-select
X*/
Xtypedef struct a_desired_symbol
X{
X char * ds_name;
X} a_desired_symbol;
X
X/*
X We'll build an array, each entry a
X struct a_desired_symbol
X*/
Xextern struct a_desired_symbol *ds_array;
Xextern long ds_next_to_use;
X /* ds_next_to_use is the count of the number of names
X supplied with -y flags
X */
Xextern long ds_allocated_count;
X /* ds_allocated_count is the number of structs
X malloc-d
X */
X#define DS_INITIAL_ALLOC 10
X#define DS_ADDITIONAL_ALLOC 10
X
X/* the -v value, as a name and an integer.
X name 0 unless -v supplied.
X*/
Xextern int value_search;
Xextern char *value_search_name;
X
X/* The -u value, as a name and an integer.
X Name 0 unless -u supplied.
X*/
Xextern int new_value;
Xextern char * new_value_name;
X
X#ifndef STO_OPTIONAL
X#define STO_OPTIONAL 4
X#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'optionalsym64.h'
then
echo shar: will not over-write existing file "'optionalsym64.h'"
else
sed 's/^X//' << \SHAR_EOF > 'optionalsym64.h'
X/*
X
X optionalsym64.h
X
X
X*/
X
X
X#ifdef HAS_ELFHDR64
Xvoid do_elf_file64(char *s);
X#endif
X
Xchar *get_shtypestring(long long x);
X
X
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0