From 739b97bdf281d703b0b4d3ffa2af22e4e40b240e Mon Sep 17 00:00:00 2001 From: "tomw%netscape.com" Date: Wed, 2 Sep 1998 02:25:40 +0000 Subject: [PATCH] Generate exports table for Cartman. This stuff needs to get moved out of mozilla at some point. --- cmd/xfe/Makefile | 14 +++ cmd/xfe/gendisp.pl | 117 +++++++++++++++++++++++ cmd/xfe/listsymb.pl | 223 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 cmd/xfe/gendisp.pl create mode 100644 cmd/xfe/listsymb.pl diff --git a/cmd/xfe/Makefile b/cmd/xfe/Makefile index 18dc3e9beb28..3aa6a5e11259 100644 --- a/cmd/xfe/Makefile +++ b/cmd/xfe/Makefile @@ -1087,7 +1087,21 @@ $(OBJDIR)/Netscape-nis-export.ad $(OBJDIR)/Netscape-export.ad: Makefile resource $(OBJDIR)/$(DSO_PROGNAME)-export: $(OBJS) $(EXPORT_OBJS) $(EXPORT_DEPLIBS) @$(MAKE_OBJDIR) rm -f $@ +ifdef BUILD_OFFICIAL + rm -rf $(OBJDIR)/objs.txt + @echo Creating a list of all object files ... objs.txt + @echo $(OBJS) > $(OBJDIR)/objs.txt + @echo $(EXPORT_OBJS) >> $(OBJDIR)/objs.txt + @echo $(DSO_EX_LIBS) >> $(OBJDIR)/objs.txt + @echo Creating a list of all symbols ... symbols.txt + $(PERL) listsymb.pl objs.txt symbols.txt + @echo Generating dispatch table ... dispunix.h dispunix.c cmoffset.h + $(PERL) gendisp.pl symbols.txt dispunix.h dispunix.c cmoffset.h + $(CC) -c -o $(OBJDIR)/dispunix.o -I$(DIST)/include dispunix.c + $(CCLD) -o $@ $(LDFLAGS) $(OBJDIR)/dispunix.o $(OBJS) $(EXPORT_OBJS) -L$(DIST)/bin -L$(DIST)/lib $(DSO_EX_LIBS) $(DNS_LIB) +else $(CCLD) -o $@ $(LDFLAGS) $(OBJS) $(EXPORT_OBJS) -L$(DIST)/bin -L$(DIST)/lib $(DSO_EX_LIBS) $(DNS_LIB) +endif @$(EXTRA_POST_LINK_CMD) $@ $(OBJDIR)/$(DSO_PROGNAME)-export.mcv: $(OBJS) $(EXPORT_OBJS) $(EXPORT_DEPLIBS) diff --git a/cmd/xfe/gendisp.pl b/cmd/xfe/gendisp.pl new file mode 100644 index 000000000000..b23573de25d9 --- /dev/null +++ b/cmd/xfe/gendisp.pl @@ -0,0 +1,117 @@ +######################################################## +# gendispw.pl +# Generates a table of pointers pointing to +# functions in Communicator being exported. +# +# The list of functions are read from the input file. +# +######################################################## + +@symbols = (); + +##################################################### +#Step 0: Get command line options +##################################################### +$input_file = $ARGV[0]; +$header_file = $ARGV[1]; +$source_file = $ARGV[2]; +$cmoffset_file = $ARGV[3]; +UsageAndExit() if (scalar(@ARGV) != 4); + +##################################################### +# Step 1: Read $input_file which contains list of functions +##################################################### +GetFunctionList($input_file, \@symbols); + +##################################################### +# Step 2: Open dispatch.h and dispatch.c for output +##################################################### +open (DISPATCH_H, ">$header_file") or die("Can't open $header_file for output.\n"); +open (DISPATCH_C, ">$source_file") or die("Can't open $source_file for output.\n"); +open (CMOFFSET_H, ">$cmoffset_file") or die("Can't open $cmoffset_file for output.\n"); + + +##################################################### +# Step 3: Write out the declarations in of header file +##################################################### +print DISPATCH_H ("#include \"nspr.h\"\n"); +print DISPATCH_H ("\n"); +print DISPATCH_H ("typedef void (*void_fun)(void);\n"); +print DISPATCH_H ("\n"); +print DISPATCH_H ("PR_EXTERN_DATA (void_fun) DISPT_Dispatch_Table[];\n"); +print DISPATCH_H ("\n"); +print DISPATCH_H ("PR_EXTERN (void_fun*) DISPT_GetDispatchTable(void);\n"); +print DISPATCH_H ("\n"); +print DISPATCH_H ("PR_EXTERN (int) DISPT_NumDispatchPoints(void);\n"); +print DISPATCH_H ("\n"); + +foreach (@symbols) { + print DISPATCH_H ("PR_EXTERN (void) $_(void);\n"); +} +print DISPATCH_H ("\n"); + +##################################################### +# Step 4: Write out the definitions in source file +##################################################### +$header_file = ExtractFilename($header_file); +print DISPATCH_C ("#include \"$header_file\"\n"); +print DISPATCH_C ("\n"); +print DISPATCH_C ("PR_IMPLEMENT_DATA (void_fun) DISPT_Dispatch_Table[] = {\n"); + +$first_entry = 1; +foreach (@symbols) { + if (!$first_entry) { + print DISPATCH_C (",\n"); + } + print DISPATCH_C ("\t$_"); + $first_entry = 0; +} + +print DISPATCH_C ("\n};\n"); +print DISPATCH_C ("\n"); +print DISPATCH_C ("PR_IMPLEMENT (void_fun*) DISPT_GetDispatchTable(void) {\n"); +print DISPATCH_C (" return DISPT_Dispatch_Table;\n"); +print DISPATCH_C ("}\n"); +print DISPATCH_C ("\n"); +print DISPATCH_C ("PR_IMPLEMENT (int) DISPT_NumDispatchPoints(void) {\n"); +print DISPATCH_C (" return (sizeof(DISPT_Dispatch_Table)/sizeof(DISPT_Dispatch_Table[0]));\n"); +print DISPATCH_C ("}\n"); + + +##################################################### +# Step 7: Write out cmoffset.h +##################################################### +$offset = 0; +foreach (@symbols) { + printf CMOFFSET_H ("#define CM_OFFSET_%-45s %5d\n",$_, $offset); + $offset++; +} + +# ---------------------- Sub-routines ------------------------- +sub UsageAndExit { + print ("Usage: perl gendisp.pl \n"); + exit(-1); +} + +# GetFunctionLIst reads in a file containing a list +# of function names, and returns an array containing +# them +sub GetFunctionList { + my($function_list) = $_[1]; + open (FUN_LIST, $_[0]) or die ("Can't open $_[0] for reading.\n"); + while ($line = ) { + if ($line =~ m/^\s*(\w+)/) { + push(@{$function_list}, $1); + } + } +} + +# Extract the filename part of a full path. +# Extracts the part of the string that appears after the last '\' or '/'. +sub ExtractFilename { + my $slash_offset = rindex($_[0], "/"); + my $bslash_offset = rindex($_[0],"\\"); + my $offset = (($slash_offset > $bslash_offset)? $slash_offset : $bslash_offset); + return substr($_[0], $offset+1); +} + diff --git a/cmd/xfe/listsymb.pl b/cmd/xfe/listsymb.pl new file mode 100644 index 000000000000..d61675fcfd7e --- /dev/null +++ b/cmd/xfe/listsymb.pl @@ -0,0 +1,223 @@ +######################################################## +# listsymb.pl +# Generates a list of all global C function names +# defined in Communicator except those with +# unwanted prefix specified below. +# +######################################################## + +# Functions with the following prefixes will not be listed. +# DISPT_GetDispatchTable & DISPT_NumDispatchPoints are exported +# using linker facilities and should always be filtered. +@unwanted_prefixes = ("__","Java_","java_","awt_","sun_","PR_", "PL_", "LL_", + "DISPT_GetDispatchTable", "DISPT_NumDispatchPoints"); + +@objfiles = (); +@symbols = (); +$debug = 0; + +#Step 1: Get command line options +$input_file = $ARGV[0]; +$output_file = $ARGV[1]; +UsageAndExit() if (scalar(@ARGV) != 2); + +# Step 2: Open output file for output +open (SYMB_LIST, ">$output_file") or die("Can't open \"$output_file\" for writing.\n"); + +# Step 3: Read input file to determine list of all obj / lib files +# needed to link the executable +GetObjFileList($input_file, \@objfiles); + +# Step 4: Run NM on every single obj / lib file +# to get the complelete list of global functions +CallNM(\@objfiles, \@symbols); + +# Step 5: Put all the symbols in output file +foreach (@symbols) { + print SYMB_LIST ("$_\n"); +} + + +# --------------- Sub-Routines ----------------- +# + + +sub UsageAndExit { + print ("Usage: perl gendisp.pl \n"); + exit(-1); +} + +# CallNM calls nm on each file in objfiles +# and finds out all symbols defined in them. +# The list of symbols is returned. +sub CallNM { + my($objfiles) = $_[0]; + my($symbols) = $_[1]; + my(%unique) = (); + + foreach (@{$objfiles}) { + my($file) = $_; + my(@results) = (); + + # if such file exists, call nm + # otherwise, print a warning + if (-f $file) { + # nm -g prints only global symbols + # nm --demangle demangles C++ names + @results = `nm --demangle -g $file`; + foreach (@results) { + my($symbol) = ExtractFunctionSymbol($_); + if ($symbol ne "") { + $unique{$symbol} = "exists"; + } + } + } + } + + foreach (sort(keys(%unique))) { + $symbol = FilterUnwantedPrefix($_); + push(@{$symbols}, ($symbol)) if $symbol ne ""; + } + +} + +sub IsObjFile { + # if 1st argument ends with .o .a or .so + if ($_[0] =~ m/\.(o)|\.(a)|\.(so)\s*$/) { + $firstchar = substr($_[0], 0, 1); + return $_[0] if $firstchar ne '/'; + } + return ""; +} + +sub IsLibFile { + ($_[0] =~ m/^\s*-l\s*(.+)\s*$/); + return $1; +} + +sub IsLibPath { + # if begins with -L, it's a path + if ($_[0] =~ m/^\s*-L\s*(.+)\s*$/) { + # Igore absolute path, because they + # tend to be system libraries + $firstchar = substr($1, 0, 1); + return "" if ($firstchar eq '/'); + + # Make sure it ends with a '/' + # so that appending it to filename will work + $lastchar = substr($1, length($1)-1, 1); + return (($lastchar eq '/')? $1 : $1.'/'); + } else { + return ""; + } +} + +# FilterUnwantedPrefix() returns 1st argument +# if +# its prefix doesn't match any of those +# defined in @unwanted_prefixes +# and +# it contains at least at least 1 upper-case letter or +# an underscore. +sub FilterUnwantedPrefix { + if ($_[0] !~ m/[A-Z_]/) { + print ("Warning: $_[0] is probably a system symbol, and so filtered.\n") if $debug > 1; + return ""; + } + foreach $prefix (@unwanted_prefixes) { + if ($_[0] =~ m/^$prefix/) { + return ""; + } + } + return $_[0]; +} + +# Returns a non-empty string if the line contains a function symbol +# Returns an empty string otherwise +# Note: a line containing a function symbol looks like this: +# 048 00000000 SECTA notype () External | _lm_DefinePkcs11 +# This function searches for entries that contains SECT,(),External +sub ExtractFunctionSymbol { + if ($_[0] =~ m/ T (\w+)\s*$/) { + print ("Matched :$_[0]\n") if $debug > 1; + return $1; + } else { + print ("Not Matched:$_[0]\n") if $debug > 1; + return ""; + } +} + +# GetObjFileLIst reads in a file containing LINK options +# and returns the list of .obj & .lib files in 1st argu +sub GetObjFileList { + my($objfiles) = $_[1]; # path to .o's, .a's, and .so's + my @libpath = (); # -Lstuff + my @libfiles = ();# -lstuff + my @junkoptions = (); # any other options + + # 1. Separate different kinds of options + open (OBJS_LIST, $_[0]) or die ("Can't open $_[0] for reading.\n"); + while ($line = ) { + # For each line, break up into words + $line =~ s/^\s+//; # eat white spaces at beginning of line + @words = split(/\s+/, $line); + foreach (@words) { + if (IsObjFile($_) ne "") { + # If the option ends with .so, .a , or .o, + # assume it is an object file to be linked in. + print ("SEPARATE: $_ is obj file.\n") if $debug; + push(@{$objfiles}, ($_)); + + } elsif (($temp = IsLibPath($_)) ne "") { + # If begins with -L + print ("SEPARATE: $_ is -L$temp.\n") if $debug; + push(@libpath, $temp); + + } elsif (($temp = IsLibFile($_)) ne "") { + # If begins with -l + print ("SEPARATE: $_ is -l$temp.\n") if $debug; + push(@libfiles, $temp); + + } else { + # Unrecognized Options + print ("SEPARATE: $_ option ignored.\n") if $debug; + push(@junkoptions, $_); + } + } + } + + # 2. check to see if .a or .so exists under the specified path + foreach (@libfiles) { + if (-f $_) { #file exists? + push (@{$objfiles}, $_); + + } else { + #file doesn't exist, try prepending libpath prefix + $file = $_; + $found = 0; + foreach (@libpath) { + if (-f $_."lib".$file.".a") { + print ("SEARCH: $_+lib+$file+.a found.\n") if $debug; + push (@{$objfiles}, $_."lib".$file.".a"); + $found = 1; + last; + + } elsif (-f $_."lib".$file.".so") { + print ("SEARCH: $_+lib+$file+.so found.\n") if $debug; + push (@{$objfiles}, $_."lib".$file.".so"); + $found = 1; + last; + + } + } + if ($found == 0) { + print ("SEARCH: $file not found.\n") if $debug; + } + } + } + + # 3. Returns the list of all object, .a, .so files + foreach (@{$objfiles}) { + print ("OBJ: $_\n") if $debug; + } +}