Optionalsym.shar

Revision as of 23:09, 31 August 2020 by Netfreak (talk | contribs) (Created page with "<pre> #! /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/...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
#! /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