XCOMM!/bin/sh -f XCOMM $Xorg: elistgen.sun,v 1.3 2000/08/17 19:41:52 cpqbld Exp $ XCOMM XCOMM ######################################################################## XCOMM Construct shared-library scoping mapfile for Solaris based on standardized XCOMM export list description file XCOMM XCOMM Usage: exportlistgen libfoo.so libfoo.elist > mapfile.scope XCOMM XCOMM libfoo.so => shared library of interest XCOMM libfoo.elist => Meta description of necessary export list. XCOMM XCOMM The output file, "mapfile.scope" may then be passed to the Solaris XCOMM linker to reconstruct the shared library, libfoo.so. XCOMM XCOMM ######################################################################## XCOMM XCOMM $XFree86: xc/config/util/elistgen.sun,v 1.8 2002/10/08 23:07:42 dawes Exp $ XCOMM Utility programs FILTER=CXXFILT # C++ symbol demangler AWK=nawk # Awk XCOMM For nm, cat, pr, sed, awk, c++filt PATH=/usr/bin:/bin:/usr/ccs/bin:/usr/ucb:$PATH XCOMM Try to detect broken versions of c++filt. if [ `echo _okay | ${FILTER:-cat}` != "_okay" ]; then if [ -x /opt/SUNWspro/bin/c++filt ]; then echo "# Your $FILTER is broken -- using /opt/SUNWspro/bin/c++filt." FILTER=/opt/SUNWspro/bin/c++filt else echo "# ERROR: no working $FILTER available." exit 1 fi; fi; XCOMM Temporary files EXPORTLIST=/tmp/elistgen1.$$ # export directives from "libfoo.list" NMLIST=/tmp/elistgen2.$$ # name list from libfoo.sl FILTLIST=/tmp/elistgen3.$$ # demangled (C++) version of above XCOMM Print useful information at the top of the output echo "#" `date` echo "# This scoping mapfile was produced by" $0 echo "# Export list description taken from:" $2 echo "# Target library:" $1 echo "# Target Operating System:" `uname -msrv` echo "# " XCOMM Extract the globally visible symbols from target library XCOMM The NMLIST generated here is later used to cross-check the symbols in the XCOMM nm stopped working on Solaris 2.5, use dump instead. nm -p $1 | $AWK '/ [ TDBS] /{print $3}' > $NMLIST XCOMM /usr/ccs/bin/dump -t -v $1 | $AWK '/(FUNC|OBJT).(GLOB|WEAK)/{print $8}' > $NMLIST XCOMM Extract the globally visible symbols from target library XCOMM The NMLIST generated here is later used to cross-check the symbols in the ${FILTER:-cat} < $NMLIST > $FILTLIST XCOMM Clean up the export-list description file. Sort the directives. $AWK ' BEGIN { csyms = 0; # C public symbols in libfoo.list cplusplus = 0; # C++ public symbols in libfoo.list isyms = 0; # C internal symbols in libfoo.list iplusplus = 0; # C++ internal symbols in libfoo.list implicit = ""; # Handling of implicit symbols } $1 == "default" { # A default clause suppresses warnings about implicit symbols. if ($2 != "" && $2 != "force" && $2 != "public" && $2 != "private" && $2 != "internal") { print "# Warning: illegal default clause:", $2 | "cat 1>&2"; next; } if (implicit != "") print "# Warning: multiple default clauses." | "cat 1>&2"; implicit = $2; next; } $1 == "force" { csyms ++; print $1 ";;" $2; next; } $1 == "public" { csyms ++; print $1 ";;" $2; next; } $1 == "publicC++" { cplusplus ++; string = $2; for (n = 3; n <= NF; n++) string = string " " $n; print $1 ";;" string; next; } $1 == "private" { csyms ++; print $1 ";;" $2; next; } $1 == "privateC++" { cplusplus ++; string = $2; for (n = 3; n <= NF; n++) string = string " " $n; print $1 ";;" string; next; } $1 == "internal" { isyms ++; print $1 ";;" $2; next; } $1 == "internalC++" { iplusplus ++; string = $2; for (n = 3; n <= NF; n++) string = string " " $n; print $1 ";;" string; next; } $1 == "#line" || $1 == "#" { # cpp will have removed comments, but may have added other stuff. next; } NF > 0 { print "# Warning: unrecognized directive:", $0 | "cat 1>&2"; next; } END { printf("# Exporting %d C and %d C++ symbols, hiding %d and %d.\n", csyms, cplusplus, isyms, iplusplus) | "cat 1>&2"; if (implicit != "") { print "# Unspecified symbols are " implicit "." | "cat 1>&2"; print "default;;" implicit; } } ' $2 1>$EXPORTLIST XCOMM Read in the above files and write result to stdout. The contents XCOMM of NMLIST and FILTLIST are used to construct a symbol lookup table. XCOMM The contents of EXPORTLIST are converted with the help of this table. XCOMM Use ";" as a delimiter in the symbol lookup table. (pr -m -s";" -t -w1024 $NMLIST $FILTLIST | sed 's/ / /g'; cat $EXPORTLIST) | $AWK ' BEGIN { FS = ";"; implicit = 0; } NF == 2 { # This is "pr" output, i.e., symbol translation table r2=$2; gsub(/static /,"",r2); # remove keyword "static" as above gsub(/ /,"",r2); # Remove spaces because c++filt is unpredictable syms[r2] = $1; r1=$1; gsub(/ /,"",r1); mangled[r1] = 1; # Save the mangling because the export lists # sometimes use it instead of a prototype. next; } NF == 3 && $1 == "default" { # Treatment of unspecified symbols. if ($3 == "internal" || $3 == "internalC++") implicit = 1; else if ($3 == "private" || $3 == "privateC++") implicit = 2; else if ($3 == "public" || $3 == "publicC++") implicit = 3; else # $3 == "force" implicit = 4; next; } NF == 3 { # Generate canonical demangled form as an alternate symbol. alt=$3; gsub(/ \.\.\./,",...",alt); # change " ..." to ",..." to match c++filt gsub(/ /,"",alt); # remove all spaces # An export directive. Parse our instructions for this symbol. if ($1 == "internal" || $1 == "internalC++") export = 1; else if ($3 == "private" || $3 == "privateC++") export = 2; else if ($3 == "public" || $3 == "publicC++") export = 3; else # $3 == "force" export = 4; # Process it. if ((length(syms[alt]) > 0) || mangled[alt]) { # This symbol is present in the library. if (donelist[alt]) print "# Warning: Duplicate entry for", $3, "in export list" | "cat 1>&2"; if (donelist[alt] < export) { donelist[alt] = export; } } else { # Print forced-export symbols without complaining. if (export == 4) { donelist[alt] = export; } else { print "# Warning:", $3, "was not in the nm list for this library" | "cat 1>&2"; } } next; } END { # Ignore magic linker symbols. if (implicit == 0) { if (!donelist["_DYNAMIC"]) donelist["_DYNAMIC"] = 1; if (!donelist["_GLOBAL_OFFSET_TABLE_"]) donelist["_GLOBAL_OFFSET_TABLE_"] = 1; if (!donelist["_PROCEDURE_LINKAGE_TABLE_"]) donelist["_PROCEDURE_LINKAGE_TABLE_"] = 1; if (!donelist["_edata"]) donelist["_edata"] = 1; if (!donelist["_end"]) donelist["_end"] = 1; if (!donelist["_etext"]) donelist["_etext"] = 1; } # Process implicit symbols. for (i in syms) { if (donelist[i] == 0 && length(syms[i]) > 0) { if (implicit == 0) { # Ignore magic symbols introduced by the C++ compiler. if ((syms[i] !~ /^__vtbl__[0-9]*_/) && (syms[i] !~ /^__ptbl_vec__/)) print "# Warning:", syms[i], "was not in the export list" | "cat 1>&2"; } else { donelist[i] = implicit; } } } # Generate the linker file. print ""; print "SUNW.1.1 {"; print " global:"; for (i in syms) if (donelist[i] >= 2 && length(syms[i]) > 0) print " " syms[i] ";"; print " local:"; print " *;"; print "};"; print ""; print "SUNW_private.1.1 {"; print " global:"; for (i in syms) if (donelist[i] == 1 && length(syms[i]) > 0) print " " syms[i] ";"; print "} SUNW.1.1;" } ' XCOMM Clean up temporary files rm $EXPORTLIST rm $NMLIST rm $FILTLIST