Mercurial > illumos > illumos-gate
changeset 2978:a77a2fdc9d9e
PSARC 2006/595 link-editor support library interface - ld_open()
6479848 Enhancements to the linker support interface needed.
6482058 lari(1) could be faster, and handle per-symbol filters better
6482974 defining virtual address of text segment can result in an invalid data segment
6476734 crle(1m) "-l" as described fails system, crle cores trying to fix /a/var/ld/ld.config in failsafe
line wrap: on
line diff
--- a/usr/src/cmd/sgs/crle/common/crle.msg Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/crle/common/crle.msg Tue Oct 24 09:55:12 2006 -0700 @@ -1,6 +1,3 @@ -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. # # CDDL HEADER START # @@ -21,6 +18,11 @@ # # CDDL HEADER END # + +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# # ident "%Z%%M% %I% %E% SMI" @@ -38,24 +40,43 @@ [-i name] [-I name] [-l dir] [-o dir ] [-s dir] \ [-t ELF|AOUT] [-u] [-v]\n\ \t[-64]\t\tprocess 64-bit objects\n\ - \t[-a name]\tadd an alternative name\n\ - \t[-A name]\tadd an optional alternative name\n\ + \t[-a name]\tdefine an alternative object name\n\ + \t[-A name]\tdefine an optional alternative object \ + name\n\ \t[-c conf]\tspecify configuration file\n\ - \t[-e env]\tadd a replaceable environment variable\n\ - \t[-E env]\tadd an permanent environment variable\n\ + \t[-e env]\tdefine a replaceable environment \ + variable\n\ + \t[-E env]\tdefine a permanent environment variable\n\ \t[-f flags]\tspecify flags for -G and -I\n\ - \t[-g name]\tadd group name\n\ - \t[-G name]\tadd group name and create \ + \t[-g name]\tdefine a group object name\n\ + \t[-G name]\tdefine a group object name and create \ alternatives\n\ - \t[-i name]\tadd individual name\n\ - \t[-I name]\tadd individual name and create \ - alternative\n\ - \t[-l dir]\tadd default search directory\n\ + \t[-i name]\tdefine an individual object name\n\ + \t[-I name]\tdefine an individual object name and \ + create an\n\ + \t\t\talternative\n\ + \t[-l dir]\tdefine a default search directory\n\ \t[-o dir]\tuse directory for alternative objects\n\ - \t[-s dir]\tadd trusted search directory\n\ + \t[-s dir]\tdefine a trusted search directory\n\ \t[-t ELF|AOUT]\ttoggle object type for -l and -s\n\ \t[-u]\t\tupdate existing configuration file\n\ - \t[-v]\t\tprovide verbose processing information\n" + \t[-v]\t\tprovide verbose processing information\n\ + \n\ + \tNote: without the -u option, the information \ + defined by the options\n\ + \tto crle() result in the replacement of any existing \ + configuration\n\ + \tfile, or default search paths. With the -u option, \ + the information\n\ + \tdefined by the options to crle() is appended to any \ + existing\n\ + \tconfiguration file, or default search paths.\n\ + \n\ + \tSet the environment variable LD_NOCONFIG=yes to \ + disable the processing\n\ + \tof any configuration file information. \ + See ld.so.1(1).\n" + @ MSG_ARG_ILLEGAL "%s: option %s has illegal argument `%s'\n" @ MSG_ARG_MULT "%s: argument %s specified multiple times\n" @@ -68,14 +89,14 @@ @ MSG_ARG_UPDATE "%s: %s: version [%d] of configuration file provides \ limited update (-u) and command-line regeneration \ capabilities: best effort in effect\n" -@ MSG_ARG_UPDATEVER "%s: %s: file version [%d] newer than crle version \ - [%d]. Unable to update\n" -@ MSG_ARG_PRINTVER "%s: %s: file version [%d] newer than crle version \ +@ MSG_ARG_UPDATEVER "%s: %s: file version [%d] newer than crle() version \ + [%d]. Unable to update\n" +@ MSG_ARG_PRINTVER "%s: %s: file version [%d] newer than crle() version \ [%d]. Displayed information may be incomplete\n" @ MSG_ARG_CLASS "%s: %s: 32-bit file is incompatible with -64 \ option\n" @ MSG_ARG_WRONGARCH "%s: %s: %s %s file is incompatible with \ - %s %s version of crle\n" + %s %s version of crle()\n" @ MSG_WARN_ENV "%s: warning: %.*s: environment variable \ multiply-defined, first definition taken\n"
--- a/usr/src/cmd/sgs/include/debug.h Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/include/debug.h Tue Oct 24 09:55:12 2006 -0700 @@ -228,6 +228,7 @@ #define Dbg_file_lazyload Dbg64_file_lazyload #define Dbg_file_ldso Dbg64_file_ldso #define Dbg_file_mode_promote Dbg64_file_mode_promote +#define Dbg_file_modified Dbg64_file_modified #define Dbg_file_needed Dbg64_file_needed #define Dbg_file_output Dbg64_file_output #define Dbg_file_preload Dbg64_file_preload @@ -422,6 +423,7 @@ #define Dbg_file_lazyload Dbg32_file_lazyload #define Dbg_file_ldso Dbg32_file_ldso #define Dbg_file_mode_promote Dbg32_file_mode_promote +#define Dbg_file_modified Dbg32_file_modified #define Dbg_file_needed Dbg32_file_needed #define Dbg_file_output Dbg32_file_output #define Dbg_file_preload Dbg32_file_preload @@ -640,6 +642,8 @@ extern void Dbg_file_ldso(Rt_map *, char **, auxv_t *, const char *, Aliste); extern void Dbg_file_mode_promote(Rt_map *, int); +extern void Dbg_file_modified(Lm_list *, const char *, const char *, + const char *, int, int, Elf *, Elf *); extern void Dbg_file_needed(Rt_map *, const char *); extern void Dbg_file_output(Ofl_desc *); extern void Dbg_file_preload(Lm_list *, const char *); @@ -728,7 +732,7 @@ extern void Dbg_seg_os(Ofl_desc *, Os_desc *, int); extern void Dbg_seg_title(Lm_list *); -extern void Dbg_shdr_modified(Lm_list *, Half, Shdr *, Shdr *, +extern void Dbg_shdr_modified(Lm_list *, const char *, Half, Shdr *, Shdr *, const char *); extern void Dbg_statistics_ar(Ofl_desc *);
--- a/usr/src/cmd/sgs/include/libld.h Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/include/libld.h Tue Oct 24 09:55:12 2006 -0700 @@ -973,6 +973,7 @@ LDS_INPUT_DONE, LDS_START, LDS_ATEXIT, + LDS_OPEN, LDS_FILE, LDS_INSEC, LDS_SEC, @@ -1063,7 +1064,7 @@ extern uintptr_t ld_init_strings(Ofl_desc *); extern uintptr_t ld_make_sections(Ofl_desc *); extern void ld_ofl_cleanup(Ofl_desc *); -extern Ifl_desc *ld_process_open(const char *, const char *, int, +extern Ifl_desc *ld_process_open(const char *, const char *, int *, Ofl_desc *, Half, Rej_desc *); extern uintptr_t ld_reloc_init(Ofl_desc *); extern uintptr_t ld_reloc_process(Ofl_desc *);
--- a/usr/src/cmd/sgs/lari/lari.pl Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/lari/lari.pl Tue Oct 24 09:55:12 2006 -0700 @@ -30,18 +30,20 @@ # # Define all global variables (required for strict) -use vars qw($Prog $DestDir $ObjRef $ObjFlag $ObjSize $TmpDir $LddArgs); -use vars qw($Glob $Intp $Cpyr $Prot $Extn $Self $Filt $Dirc $Plta $User $Func); -use vars qw($Objt $UndefSym $IgnSyms $Rtld $MultSyms $CrtSyms $GlobWeak); -use vars qw($DbgSeed %opt %Symbols %Objects %Versioned %DemSyms); -use vars qw($Platform $Nodi $Osft $Oaft $Ssft $Saft $Msft); +use vars qw($Prog $DestDir $ObjRef $ObjFlag $ObjSize $TmpDir $LddArgs $SymFlag); +use vars qw($Glob $Intp $Dirc $Cpyr $Prot $Extn $Self $Gfte $Plta $User $Func); +use vars qw($Sfte $Afte $Objt $Nodi $Osft $Oaft $Ssft $Saft $Msft); +use vars qw($Rtld $GlobWeak $MultSyms $CrtSyms $Platform $DbgSeed %opt); + +# Global arrays that must be cleared for multi input file use. +use vars qw(%Symbols %Objects %Versioned %DemSyms %ObjFltrs %SymFltes); use strict; use Getopt::Std; use File::Basename; -# Pattern match to skip objects. +# Pattern match to skip the runtime linker. $Rtld = qr{ /lib/ld\.so\.1 | /usr/lib/ld\.so\.1 | @@ -83,27 +85,17 @@ )$ }x; -# Pattern match to remove undefined, NOTY and versioning symbols. -$UndefSym = qr{ ^(?: - UNDEF - )$ -}x; - -$IgnSyms = qr{ ^(?: - NOTY | - ABS - )$ -}x; - # Symbol flags. $Glob = 0x00001; # symbol is global +$Sfte = 0x00002; # symbol is a filtee backing a standard filter +$Afte = 0x00004; # symbol is a filtee backing a auxiliary filter +$Gfte = 0x00008; # symbol bound as a filtee $Intp = 0x00010; # symbol originates for explicit interposer $Dirc = 0x00020; # symbol bound to directly $Cpyr = 0x00040; # symbol bound to copy-relocation reference $Prot = 0x00080; # symbol is protected (symbolic) $Extn = 0x00100; # symbol has been bound to from an external reference $Self = 0x00200; # symbol has been bound to from the same object -$Filt = 0x00400; # symbol bound to a filtee $Plta = 0x00800; # symbol bound to executables plt address $User = 0x01000; # symbol binding originates from user (dlsym) request $Func = 0x02000; # symbol is of type function @@ -113,7 +105,7 @@ $Osft = 0x10000; # symbol is an standard object filter $Oaft = 0x20000; # symbol is an auxiliary object filter $Ssft = 0x40000; # symbol is a per-symbol standard filter -$Saft = 0x80000; # symbol is a per-symbol auxilary filter +$Saft = 0x80000; # symbol is a per-symbol auxiliary filter $Msft = 0xf0000; # filter mask # Offsets into $Symbols{$SymName}{$Obj} array. @@ -121,6 +113,8 @@ $ObjFlag = 1; $ObjSize = 2; +# Offset into $SymFltr{$SymName}{$Filtee} array. +$SymFlag = 0; # Establish locale use POSIX qw(locale_h); @@ -146,7 +140,7 @@ } } -# Cleanup any temporary files on interruption +# Cleanup any temporary files on interruption. sub Cleanup { my ($Sig) = @_; @@ -172,8 +166,7 @@ print STDERR gettext("\t[-a] print diagnostics for all symbols\n"); print STDERR - gettext("\t[-b] print diagnostics for multiple-bound " . - "symbols\n"); + gettext("\t[-b] limit diagnostics to bound symbols\n"); print STDERR gettext("\t[-C] print demangled symbol names also\n"); print STDERR @@ -185,7 +178,7 @@ print STDERR gettext("\t[-m] create mapfiles for interface requirements\n"); print STDERR - gettext("\t[-o] print overhead information\n"); + gettext("\t[-o] limit diagnostics to overhead information\n"); print STDERR gettext("\t[-s] save bindings information created by ldd(1)\n"); print STDERR @@ -358,7 +351,7 @@ next; } - # If we're decending into a platform directory, ignore + # If we're descending into a platform directory, ignore # any inappropriate platform specific files. These # files can have dependencies that in turn bring in the # appropriate platform specific file, resulting in more @@ -524,6 +517,9 @@ %Symbols = (); %Objects = (); %Versioned = (); + %DemSyms = (); + %ObjFltrs = (); + %SymFltes = (); } # As debugging output can be significant, read a line at a time. @@ -531,45 +527,6 @@ while (defined(my $Line = <$FileHandle>)) { chomp($Line); - # If we find a relationship between a filter and filtee, save - # it, we'll come back to this once we've gathered everybodies - # symbols. - if ($Line =~ /; filtered by /) { - my ($Filtee) = $Line; - my ($Filter) = $Line; - - # Separate the filter and filtee names, ignore the - # runtime linker. - $Filtee =~ s/^.*: file=(.*); filtered by .*/$1/; - if ($Filtee =~ $Rtld) { - next; - } - $Filter =~ s/^.*; filtered by //; - $Filtees{$Filtee}{$Filter} = 1; - next; - } - - # If we find a configuration alternative, determine whether it - # is for one of our filtees, and if so record it. - if ($Line =~ / configuration alternate found:/) { - my ($Orig) = $Line; - my ($Altr) = $Line; - - # Separate the original and alternative names. - $Orig =~ s/^.*: file=(.*) .*$/$1/; - $Altr =~ s/^.* configuration alternate found: (.*)$/$1/; - - for my $Filtee (keys(%Filtees)) { - if ($Filtee ne $Orig) { - next; - } - for my $Filter (keys(%{$Filtees{$Filtee}})) { - $Filtees{$Altr}{$Filter} = 1; - } - } - next; - } - # Collect the symbols from any file analyzed. if ($Line =~ /^.*: file=(.*); analyzing .*/) { GetAllSymbols($1); @@ -602,7 +559,7 @@ # of the reference, "(0x1234...)", but in the case of a # user lookup it's the string "(dlsym)". If we don't # find this offset information we've been given a debug - # file that didn't user the "datail" token, in which case + # file that didn't use the "detail" token, in which case # we're not getting all the information we need. if ($Fields[$Offset] =~ /^\((.*)\)/) { if ($1 eq 'dlsym') { @@ -680,8 +637,8 @@ $Objects{$DstFile}{$SymName} |= $Cpyr; } if ($BndInfo =~ /filtee/) { - $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Filt; - $Objects{$DstFile}{$SymName} |= $Filt; + $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Gfte; + $Objects{$DstFile}{$SymName} |= $Gfte; } if ($BndInfo =~ /interpose/) { $Symbols{$SymName}{$DstFile}[$ObjFlag] |= $Intp; @@ -699,40 +656,107 @@ } close($FileHandle); - # Now that we've processed all objects, complete any auxiliary filtee - # tagging. For each filtee, determine which of the symbols it exports - # are also defined in its filters. If a filtee is bound to, the + # Now that we've processed all objects, traverse the set of object + # filters that have been captured from parsing any FILTER and AUXILIARY + # dynamic tags. For each filtee, determine which of the symbols it + # exports are also defined in the filter. If a filter is bound to, the # runtime linkers diagnostics will indicate a filtee binding. However, # some of the filtee symbols may not be bound to, so here we mark them # all so as to remove them from any interesting output. - for my $Filtee (keys(%Filtees)) { + for my $Filter (keys(%ObjFltrs)) { + + # Determine the filtees that are associated with this filter. + for my $Filtee (keys(%{$ObjFltrs{$Filter}})) { + my ($FileName); + + # Reduce the filtee to a simple file name. Then, try + # and associate this simple file name with the objects + # that have been processed. These objects are typically + # recorded with a full path name. + chomp($FileName = `basename $Filtee`); + for my $Obj (keys(%Objects)) { + if ($Obj =~ /\/$FileName$/) { + $Filtee = $Obj; + last; + } + } + + if (!exists($Objects{$Filtee})) { + next; + } + + # Traverse the symbols of the filtee (these are + # typically a smaller set than the filter) and if the + # symbol is defined by the filter tag the symbol as a + # filtee. + for my $SymName (keys(%{$Objects{$Filtee}})) { + my ($OFlag, $FFlag); + + # Ignore the usual stuff. + if (($SymName =~ $MultSyms) || + ($SymName =~ $CrtSyms)) { + next; + } - # Standard filters aren't captured at all, as nothing can bind - # to them. - if (!exists($Objects{$Filtee})) { + if (!$Symbols{$SymName}{$Filter}) { + next; + } + + # Determine the type of filter. + $OFlag = $Symbols{$SymName}{$Filter}[$ObjFlag]; + + # Specifically identify the type of filtee we + # have and remove any generic filtee flag. + if ($OFlag & ($Osft | $Ssft)) { + $FFlag = $Sfte; + } else { + $FFlag = $Afte; + } + + $Symbols{$SymName}{$Filtee}[$ObjFlag] |= $FFlag; + $Symbols{$SymName}{$Filtee}[$ObjFlag] &= ~$Gfte; + } + } + } + + # Traverse the set of per-symbol filters making sure we've tagged any + # associated filtee symbols, as we did above for object filters. + for my $Filtee (keys(%SymFltes)) { + my ($FullPath) = $Filtee; + my ($FileName); + + # Reduce the filtee to a simple file name. Then, try and + # associate this simple file name with the objects that have + # been processed. These objects are typically recorded with a + # full path name. + chomp($FileName = `basename $Filtee`); + for my $Obj (keys(%Objects)) { + if ($Obj =~ /\/$FileName$/) { + $FullPath = $Obj; + last; + } + } + + if (!exists($Objects{$FullPath})) { next; } - # Determine what symbols this filtee offers. - foreach my $SymName (keys(%{$Objects{$Filtee}})) { + for my $SymName (keys(%{$SymFltes{$Filtee}})) { + my ($OFlag, $FFlag); + + # Determine the type of filter. + $OFlag = $SymFltes{$Filtee}{$SymName}[$SymFlag]; - # Ignore the usual reserved stuff. - if (!$opt{a} && (($SymName =~ $MultSyms) || - ($SymName =~ $CrtSyms))) { - next; + # Specifically identify the type of filtee we have and + # remove any generic filtee flag. + if ($OFlag & $Ssft) { + $FFlag = $Sfte; + } else { + $FFlag = $Afte; } - # Determine whether this symbol exists in our filter. - for my $Filter (keys(%{$Filtees{$Filtee}})) { - if (!$Symbols{$SymName}{$Filter}) { - next; - } - if (!($Symbols{$SymName}{$Filter}[$ObjFlag] & - $Msft)) { - next; - } - $Symbols{$SymName}{$Filtee}[$ObjFlag] |= $Filt; - } + $Symbols{$SymName}{$FullPath}[$ObjFlag] |= $FFlag; + $Symbols{$SymName}{$FullPath}[$ObjFlag] &= ~$Gfte; } } @@ -777,7 +801,7 @@ # symbols that have been bound to from an # external object, or must be global to enable # a binding to an interposing definition. - # Skip bindings to ourself as these are + # Skip bindings to ourself, as these are # candidates for demoting to local. if (!($Flag & ($Extn | $Intp))) { next; @@ -880,11 +904,14 @@ # If we haven't been asked for all symbols, only # print those reserved symbols that have been # bound to, as the number of reserved symbols - # can be quite excessive. + # can be quite excessive. Also, remove any + # standard filters, as nothing can bind to these + # symbols anyway. if (!$opt{a} && ((($SymName =~ $MultSyms) && (($Flag & ($Extn | $Self)) == 0)) || (($SymName =~ $CrtSyms) && (($Flag & - ($Extn | $Self | $Prot)) == 0)))) { + ($Extn | $Self | $Prot)) == 0)) || + ($Flag & ($Ssft | $Osft)))) { next; } @@ -925,7 +952,7 @@ $Str = $Str . 'C'; } # Is this symbol part of filtee. - if ($Flag & $Filt) { + if ($Flag & ($Sfte | $Afte | $Gfte)) { $Str = $Str . 'F'; } # Is this symbol protected (in which case there @@ -947,7 +974,7 @@ if ($Flag & $Msft) { $Str = $Str . 'R'; } - # Does this definition explicity define no + # Does this definition explicitly define no # direct binding. if ($Flag & $Nodi) { $Str = $Str . 'N'; @@ -995,24 +1022,33 @@ { my ($SymName) = @_; my ($ObjCnt, $GFlags, $BndCnt, $FltCnt, $NodiCnt, $RdirCnt, $ExRef); + my ($TotCnt); # Scan all definitions of this symbol, thus determining the definition # count, the number of filters, redirections, executable references # (copy-relocations, or plt addresses), no-direct bindings, and the # number of definitions that have been bound to. $ObjCnt = $GFlags = $BndCnt = $FltCnt = - $NodiCnt = $RdirCnt = $ExRef = 0; + $NodiCnt = $RdirCnt = $ExRef = $TotCnt = 0; foreach my $Obj (keys(%{$Symbols{$SymName}})) { my ($Flag) = $Symbols{$SymName}{$Obj}[$ObjFlag]; + $TotCnt++; + # Ignore standard filters when determining the symbol count, as # a standard filter can never be bound to. if (($Flag & ($Osft | $Ssft)) == 0) { $ObjCnt++; } + # If we're only looking at interesting objects, then standard + # filters are ignored, so suppress any standard filtee tagging. + if (!$opt{a}) { + $Flag = $Symbols{$SymName}{$Obj}[$ObjFlag] &= ~$Sfte; + } + $GFlags |= $Flag; - if ($Flag & $Filt) { + if ($Flag & ($Sfte | $Afte | $Gfte)) { $FltCnt++; } if ($Flag & $Nodi) { @@ -1044,7 +1080,7 @@ # If we want all symbols, return the count. If we want all bound # symbols, return the count provided it is non-zero. if ($opt{a} && (!$opt{b} || ($BndCnt > 0))) { - return $ObjCnt; + return $TotCnt; } # Single instance symbol definitions aren't very interesting. @@ -1117,13 +1153,18 @@ # object has been versioned. sub GetAllSymbols { my ($Obj) = @_; - my (@Elfd, @Elfs, @Elfr, $Type, $Exec, $FileHandle); + my ($Type, $FileHandle); my (%AddrToName, %NameToAddr); + my ($Exec) = 0; my ($Vers) = 0; my ($Symb) = 0; my ($Copy) = 0; my ($Interpose) = 0; my ($Fltr) = 0; + my ($Ehdr) = 0; + my ($Dyn) = 0; + my ($Rel) = 0; + my ($Info) = 0; # Determine whether we've already retrieved this object's symbols. # Also, ignore the runtime linker, it's on a separate link-map, and @@ -1139,76 +1180,135 @@ return; } - # Get the dynamic information. - @Elfd = split(/\n/, `LC_ALL=C elfdump -d '$Obj' 2> /dev/null`); + # Get as much ELF information as we can from elfdump(1). A second + # invocation of elfdump(1) is required to obtain the symbol table, whose + # processing can be affected by states determined during this pass. + # + # The information required: + # -e ELF header provides the file type + # -d dynamic information provides filter names + # -r relocations provide for copy relocations + # -y symbol information section provide pre-symbol filters + # and direct binding information + # + # As this information can be quite large, process the elfdump(1) output + # through a pipe. + open($FileHandle, "LC_ALL=C elfdump -edry '$Obj' 2> /dev/null |"); - # If there's no information, it's possible we've been given a debug - # output file and are processing it from a location from which the - # dependencies specified in the debug file aren't accessible. - if (!@Elfd) { - printf STDERR gettext("%s: %s: unable to process ELF file\n"), - $Prog, $Obj; + while (defined(my $Line = <$FileHandle>)) { + my (@Fields); + + chomp($Line); - # Add the file to our list, so that we don't create the same - # message again. Processing should continue so that we can - # flush out as many error messages as possible. - $Objects{$Obj}{"DoesNotExist"} = 0; - return; - } + # Each collection of data is preceded with a title that + # starts in column 0. Items of data all have some form of + # indentation. + if ($Line =~ /^[A-Z]/) { + if ($Line =~ /^ELF Header/) { + $Ehdr = 1; + $Dyn = $Rel = $Info = 0; + } elsif ($Line =~ /^Dynamic Section:/) { + $Dyn = 1; + $Ehdr = $Rel = $Info = 0; + } elsif ($Line =~ /^Relocation Section:/) { + $Rel = 1; + $Ehdr = $Dyn = $Info = 0; + } elsif ($Line =~ /^Syminfo Section:/) { + $Info = 1; + $Ehdr = $Dyn = $Rel = 0; + } else { + $Ehdr = $Dyn = $Rel = $Info = 0; + } + next; + } - # If we're processing a filter there's no need to save any symbols, as - # no bindings will occur to this object. - # - # Determine whether we've got a symbolicly bound object. With newer - # linkers all symbols will be marked as protected ("P"), but with older - # linkers this state could only be intuited from the symbolic dynamic - # tag. - foreach my $Line (@Elfd) { - my (@Fields); - @Fields = split(' ', $Line); + # Inspect the ELF header. + if ($Ehdr eq 1) { + # Determine the ELF file type from the e_type element. + if ($Line =~ /e_type:/) { + if ($Line =~ /ET_EXEC/) { + $Exec = 1; + } - # Determine if the FILTER tag is set. - if ($#Fields == 3) { - if ($Fields[1] eq "FILTER") { - $Fltr |= $Osft; + # There's nothing of interest left in the ELF + # header, so skip processing other entries. + $Ehdr = 0; next; } - if ($Fields[1] eq "AUXILIARY") { - $Fltr |= $Oaft; + } + + # Inspect the .dynamic section. + if ($Dyn eq 1) { + @Fields = split(' ', $Line); + + # Determine if the FILTER or AUXILIARY tag is set. + if ($#Fields == 3) { + my ($Flte) = 0; + + if ($Fields[1] eq 'FILTER') { + $Fltr |= $Osft; + $Flte = 1; + } + elsif ($Fields[1] eq 'AUXILIARY') { + $Fltr |= $Oaft; + $Flte = 1; + } + if ($Flte eq 1) { + my (@Filtees) = split(':', $Fields[3]); + + for my $Filtee (@Filtees) { + if ($Filtee =~ $Rtld) { + next; + } + $ObjFltrs{$Obj}{$Filtee} = 1; + } + } + next; + } + + # We're only interested in the FLAGS entry. + if (($#Fields < 4) || ($Fields[1] !~ /^FLAGS/)) { + next; + } + + # Determine whether we've got a symbolicly bound object. + # With newer link-editors, all symbols will be marked as + # protected ("P"), but with older link-editors this + # state could only be inferred from the symbolic dynamic + # tag. + if (($Fields[1] eq 'FLAGS') && + ($Line =~ / SYMBOLIC /)) { + $Symb = 1; + next; + } + + # Determine whether this object is an interposer. + if (($Fields[1] eq 'FLAGS_1') && + ($Line =~ / INTERPOSE /)) { + $Interpose = 1; next; } next; } - # We're only interested in the FLAGS entry. - if (($#Fields < 4) || ($Fields[1] !~ "^FLAGS")) { - next; - } - if (($Fields[1] eq "FLAGS") && ($Line =~ " SYMBOLIC ")) { - $Symb = 1; - next; - } - if (($Fields[1] eq "FLAGS_1") && ($Line =~ " INTERPOSE ")) { - $Interpose = 1; - } - } + # Inspect the relocation information. As we're only looking + # for copy relocations, this processing is only necessary for + # executables. + if ($Rel eq 1) { + my ($SymName); - # If this file is a dynamic executable, determine if this object has - # any copy relocations so that any associated bindings can be labeled - # more meaningfully. - $Type = `LC_ALL=C file '$Obj'`; - if ($Type =~ /executable/) { - $Exec = 1; - # Obtain any copy relocations. - @Elfr = split(/\n/, `LC_ALL=C elfdump -r '$Obj' 2>&1`); - - foreach my $Rel (@Elfr) { - my ($SymName, @Fields); - - if ($Rel !~ / R_[A-Z0-9]+_COPY /) { + if ($Exec eq 0) { + $Rel = 0; next; } - @Fields = split(' ', $Rel); + + # Obtain any copy relocations. + if ($Line !~ / R_[A-Z0-9]+_COPY /) { + next; + } + + @Fields = split(' ', $Line); + # Intel relocation records don't contain an addend, # where as every other supported platform does. if ($Fields[0] eq 'R_386_COPY') { @@ -1221,48 +1321,114 @@ $Objects{$Obj}{$SymName} |= $Cpyr; $Copy = 1; } - } else { - $Exec = 0; + + # Inspect the .SUNW_syminfo section. + if ($Info eq 1) { + my ($SymName); + my ($Flags) = 0; + + @Fields = split(' ', $Line); + + # Binding attributes are in the second column. + if ($#Fields < 1) { + next; + } + if ($Fields[1] =~ /N/) { + $Flags |= $Nodi; + } + if ($Fields[1] =~ /F/) { + $Flags |= $Ssft; + } + if ($Fields[1] =~ /A/) { + $Flags |= $Saft; + } + + # Determine the symbol name based upon the number of + # fields. + if ($Flags) { + $SymName = $Fields[$#Fields]; + $Symbols{$SymName}{$Obj}[$ObjFlag] |= $Flags; + $Objects{$Obj}{$SymName} |= $Flags; + } + + # If this is a filter, we need to tag the associated + # filtee symbol. However, the filtee might not have + # been processed yet, so save this information for later. + $Flags &= ~$Nodi; + if ($Flags) { + my ($Filtee) = $Fields[$#Fields - 1]; + + if ($Filtee =~ $Rtld) { + next; + } + $SymFltes{$Filtee}{$SymName}[$SymFlag] = $Flags; + } + } } - # Obtain the dynamic symbol table for this object. Symbol tables can - # be quite large, so open the elfump command through a pipe. + close($FileHandle); + + # If there's no expected information, it's possible we've been given a + # debug output file and are processing the file from a location from + # which the dependencies specified in the debug file aren't accessible. + if ($Dyn eq 0) { + printf STDERR gettext("%s: %s: unable to process ELF file\n"), + $Prog, $Obj; + + # Add the file to our list, so that we don't create the same + # message again. Processing should continue so that we can + # flush out as many error messages as possible. + $Objects{$Obj}{"DoesNotExist"} = 0; + return; + } + + # Process elfdump(1) once more to obtain the .dynsym symbol table. open($FileHandle, "LC_ALL=C elfdump -sN.dynsym '$Obj' 2> /dev/null |"); - # Now process all symbols. while (defined(my $Line = <$FileHandle>)) { chomp($Line); my (@Fields) = split(' ', $Line); my ($Flags); - # We're only interested in defined non-reserved symbol entries. - # Note, ABS and NOTY symbols of non-zero size have been known to - # occur, so capture them. + # We're only interested in defined symbol entries. Unless + # we've been asked for all symbols, ignore any ABS or NOTY + # symbols. The former are typically reserved symbols or + # versioning names. The latter are labels that are not bound + # to. Note, ABS and NOTY symbols of non-zero size have been + # known to occur, so capture them. if (($#Fields < 8) || ($Fields[4] !~ $GlobWeak) || - ($Fields[7] =~ $UndefSym) || (!$opt{a} && - ($Fields[7] =~ $IgnSyms) && (oct($Fields[2]) eq 0))) { + ($Fields[7] eq 'UNDEF') || + (!$opt{a} && (oct($Fields[2]) eq 0) && + ((($Fields[7] eq 'ABS') && ($Fields[3] eq 'OBJT')) || + ($Fields[3] eq 'NOTY')))) { next; } - # If we're found copy relocations, save the address and names - # of any OBJT definitions, together with the copy symbol. - if ($Copy && ($Fields[3] eq 'OBJT')) { + # If we're found copy relocations, save the address of all OBJT + # definitions, together with the copy symbol. These definitions + # are used to determine whether the copy symbol has any aliases + # (ie. __iob and _iob). + if (($Copy eq 1) && ($Fields[3] eq 'OBJT')) { push(@{$AddrToName{$Fields[1]}}, $Fields[8]); - } - if (($Symbols{$Fields[8]}{$Obj}) && - ($Symbols{$Fields[8]}{$Obj}[$ObjFlag] & $Cpyr)) { - $NameToAddr{$Fields[8]} = $Fields[1]; + + if (($Symbols{$Fields[8]}{$Obj}) && + ($Symbols{$Fields[8]}{$Obj}[$ObjFlag] & $Cpyr)) { + $NameToAddr{$Fields[8]} = $Fields[1]; + } } + # Identify this symbol as global, and associate it with any + # object filtering. + $Flags = $Glob | $Fltr; + # If the symbol visibility is protected, this is an internal - # symbolic binding (NOTE, an INTERNAL visibility for a global + # symbolic binding. Note, an INTERNAL visibility for a global # symbol is invalid, but for a while ld(1) was setting this - # attribute mistakenly for protected). - # If this is a dynamic executable, mark its symbols as protected - # (they can't be interposed on any more than symbols defined + # attribute mistakenly for protected. If this is a dynamic + # executable, mark its symbols as protected. These symbols + # can't be interposed on any more than symbols defined as # protected within shared objects). - $Flags = $Glob | $Fltr; if (($Fields[5] =~ /^[IP]$/) || $Symb || $Exec) { $Flags |= $Prot; } @@ -1273,8 +1439,8 @@ } # Identify the symbol as a function or data type, and for the - # latter, capture the symbol size. Ignore the standard - # symbolic labels, as we don't want to type them. + # latter, capture the symbol size. Ignore the standard symbolic + # labels, as we don't want to type them. if ($Fields[8] !~ $MultSyms) { if ($Fields[3] =~ /^FUNC$/) { $Flags |= $Func; @@ -1303,41 +1469,8 @@ } close($FileHandle); - # Obtain any symbol information table for this object. Symbol tables can - # be quite large, so open the elfump command through a pipe. - open($FileHandle, "LC_ALL=C elfdump -y '$Obj' 2> /dev/null |"); - - # Now process all symbols. - while (defined(my $Line = <$FileHandle>)) { - chomp($Line); - - my (@Fields) = split(' ', $Line); - my ($Flags) = 0; - - # Binding attributes are in the second column. - if ($#Fields < 1) { - next; - } - if ($Fields[1] =~ /N/) { - $Flags |= $Nodi - } - if ($Fields[1] =~ /F/) { - $Flags |= $Ssft; - } - if ($Fields[1] =~ /A/) { - $Flags |= $Saft; - } - - # Determine the symbol name based upon the number of fields. - if ($Flags && $Symbols{$Fields[$#Fields]}{$Obj}) { - $Symbols{$Fields[$#Fields]}{$Obj}[$ObjFlag] |= $Flags; - $Objects{$Obj}{$Fields[$#Fields]} |= $Flags; - } - } - close($FileHandle); - - # If this symbol has already been marked as a copy-relocation reference, - # see if this symbol has any aliases, which should also be marked. + # Process any copy relocation symbols to see if the copy symbol has any + # aliases, which should also be marked as copy relocations. if ($Copy) { foreach my $SymName (keys(%NameToAddr)) { my ($Addr) = $NameToAddr{$SymName};
--- a/usr/src/cmd/sgs/libld/common/_libld.h Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/_libld.h Tue Oct 24 09:55:12 2006 -0700 @@ -284,6 +284,7 @@ #define ld_sort_seg_list ld64_sort_seg_list #define ld_sunwmove_preprocess ld64_sunwmove_preprocess #define ld_sup_atexit ld64_sup_atexit +#define ld_sup_open ld64_sup_open #define ld_sup_file ld64_sup_file #define ld_sup_loadso ld64_sup_loadso #define ld_sup_input_done ld64_sup_input_done @@ -380,6 +381,7 @@ #define ld_sort_seg_list ld32_sort_seg_list #define ld_sunwmove_preprocess ld32_sunwmove_preprocess #define ld_sup_atexit ld32_sup_atexit +#define ld_sup_open ld32_sup_open #define ld_sup_file ld32_sup_file #define ld_sup_loadso ld32_sup_loadso #define ld_sup_input_done ld32_sup_input_done @@ -503,6 +505,9 @@ extern uintptr_t ld_sort_seg_list(Ofl_desc *); extern uintptr_t ld_sunwmove_preprocess(Ofl_desc *); extern void ld_sup_atexit(Ofl_desc *, int); +extern void ld_sup_open(Ofl_desc *, const char **, const char **, + int *, int, Elf **, Elf *ref, size_t, + const Elf_Kind); extern void ld_sup_file(Ofl_desc *, const char *, const Elf_Kind, int flags, Elf *); extern uintptr_t ld_sup_loadso(Ofl_desc *, const char *);
--- a/usr/src/cmd/sgs/libld/common/args.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/args.c Tue Oct 24 09:55:12 2006 -0700 @@ -1511,9 +1511,10 @@ DBG_CALL(Dbg_args_files(ofl->ofl_lml, optind, path)); - ifl = ld_process_open(path, path, fd, ofl, + ifl = ld_process_open(path, path, &fd, ofl, (FLG_IF_CMDLINE | FLG_IF_NEEDED), &rej); - (void) close(fd); + if (fd != -1) + (void) close(fd); if (ifl == (Ifl_desc *)S_ERROR) return (S_ERROR);
--- a/usr/src/cmd/sgs/libld/common/files.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/files.c Tue Oct 24 09:55:12 2006 -0700 @@ -2058,18 +2058,39 @@ * archive (see libs.c: ld_process_archive()). */ Ifl_desc * -ld_process_open(const char *path, const char *file, int fd, Ofl_desc *ofl, +ld_process_open(const char *opath, const char *ofile, int *fd, Ofl_desc *ofl, Half flags, Rej_desc *rej) { - Elf *elf; + Elf *elf; + const char *npath = opath; + const char *nfile = ofile; - if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { - eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_BEGIN), path); + if ((elf = elf_begin(*fd, ELF_C_READ, NULL)) == NULL) { + eprintf(ofl->ofl_lml, ERR_ELF, MSG_INTL(MSG_ELF_BEGIN), npath); ofl->ofl_flags |= FLG_OF_FATAL; return (0); } - return (ld_process_ifl(path, file, fd, elf, flags, ofl, rej)); + /* + * Determine whether the support library wishes to process this open. + * The support library may return: + * . a different ELF descriptor (in which case they should have + * closed the original) + * . a different file descriptor (in which case they should have + * closed the original) + * . a different path and file name (presumably associated with + * a different file descriptor) + * + * A file descriptor of -1, or and ELF descriptor of zero indicates + * the file should be ignored. + */ + ld_sup_open(ofl, &npath, &nfile, fd, flags, &elf, NULL, 0, + elf_kind(elf)); + + if ((*fd == -1) || (elf == NULL)) + return (0); + + return (ld_process_ifl(npath, nfile, *fd, elf, flags, ofl, rej)); } /* @@ -2121,8 +2142,9 @@ if ((_path = libld_malloc(strlen(path) + 1)) == 0) return ((Ifl_desc *)S_ERROR); (void) strcpy(_path, path); - ifl = ld_process_open(_path, &_path[dlen], fd, ofl, NULL, rej); - (void) close(fd); + ifl = ld_process_open(_path, &_path[dlen], &fd, ofl, NULL, rej); + if (fd != -1) + (void) close(fd); return (ifl); } } @@ -2197,9 +2219,10 @@ } else { Rej_desc _rej = { 0 }; - ifl = ld_process_open(file, ++slash, fd, ofl, + ifl = ld_process_open(file, ++slash, &fd, ofl, NULL, &_rej); - (void) close(fd); + if (fd != -1) + (void) close(fd); if (ifl == (Ifl_desc *)S_ERROR) { return (S_ERROR);
--- a/usr/src/cmd/sgs/libld/common/ldlibs.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/ldlibs.c Tue Oct 24 09:55:12 2006 -0700 @@ -203,9 +203,10 @@ return ((Ifl_desc *)S_ERROR); (void) strcpy(_path, path); - ifl = ld_process_open(_path, &_path[dlen], fd, ofl, + ifl = ld_process_open(_path, &_path[dlen], &fd, ofl, FLG_IF_NEEDED, rej); - (void) close(fd); + if (fd != -1) + (void) close(fd); return (ifl); } else if (errno != ENOENT) { @@ -232,9 +233,10 @@ return ((Ifl_desc *)S_ERROR); (void) strcpy(_path, path); - ifl = ld_process_open(_path, &_path[dlen], fd, ofl, + ifl = ld_process_open(_path, &_path[dlen], &fd, ofl, FLG_IF_NEEDED, rej); - (void) close(fd); + if (fd != -1) + (void) close(fd); return (ifl); } else if (errno != ENOENT) {
--- a/usr/src/cmd/sgs/libld/common/libld.msg Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/libld.msg Tue Oct 24 09:55:12 2006 -0700 @@ -717,12 +717,14 @@ @ MSG_SUP_START_64 "ld_start64" @ MSG_SUP_ATEXIT_64 "ld_atexit64" +@ MSG_SUP_OPEN_64 "ld_open64" @ MSG_SUP_FILE_64 "ld_file64" @ MSG_SUP_INSEC_64 "ld_input_section64" @ MSG_SUP_SEC_64 "ld_section64" @ MSG_SUP_START "ld_start" @ MSG_SUP_ATEXIT "ld_atexit" +@ MSG_SUP_OPEN "ld_open" @ MSG_SUP_FILE "ld_file" @ MSG_SUP_INSEC "ld_input_section" @ MSG_SUP_SEC "ld_section"
--- a/usr/src/cmd/sgs/libld/common/libs.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/libs.c Tue Oct 24 09:55:12 2006 -0700 @@ -402,6 +402,7 @@ ofl->ofl_flags |= FLG_OF_FATAL; return (0); } + if ((arelf = elf_begin(fd, ELF_C_READ, adp->ad_elf)) == NULL) { eprintf(ofl->ofl_lml, ERR_ELF, @@ -430,6 +431,17 @@ return (S_ERROR); (void) snprintf(arpath, len, MSG_ORIG(MSG_FMT_ARMEM), name, arname); + + /* + * Determine whether the support library wishes + * to process this open. See comments in + * ld_process_open(). + */ + ld_sup_open(ofl, (const char **)&arpath, + (const char **)&arname, &fd, + (FLG_IF_EXTRACT | FLG_IF_NEEDED), + &arelf, adp->ad_elf, arsym->as_off, + elf_kind(arelf)); } /* @@ -484,7 +496,7 @@ DBG_CALL(Dbg_syms_ar_resolve(ofl->ofl_lml, ndx, arsym, arname, allexrt)); if ((err = (uintptr_t)ld_process_ifl(arpath, NULL, fd, - arelf, FLG_IF_EXTRACT | FLG_IF_NEEDED, ofl, + arelf, (FLG_IF_EXTRACT | FLG_IF_NEEDED), ofl, &_rej)) == S_ERROR) return (S_ERROR);
--- a/usr/src/cmd/sgs/libld/common/llib-lld Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/llib-lld Tue Oct 24 09:55:12 2006 -0700 @@ -50,10 +50,10 @@ void ld32_ofl_cleanup(Ofl_desc *); void ld64_ofl_cleanup(Ofl_desc *); -Ifl_desc *ld32_process_open(const char *, const char *, int, Ofl_desc *, - Elf32_Half, Rej_desc *); -Ifl_desc *ld64_process_open(const char *, const char *, int, Ofl_desc *, - Elf64_Half, Rej_desc *); +Ifl_desc *ld32_process_open(const char *, const char *, int *, + Ofl_desc *, Elf32_Half, Rej_desc *); +Ifl_desc *ld64_process_open(const char *, const char *, int *, + Ofl_desc *, Elf64_Half, Rej_desc *); uintptr_t ld32_reloc_init(Ofl_desc *); uintptr_t ld64_reloc_init(Ofl_desc *);
--- a/usr/src/cmd/sgs/libld/common/support.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/support.c Tue Oct 24 09:55:12 2006 -0700 @@ -45,12 +45,14 @@ #if defined(_ELF64) {MSG_ORIG(MSG_SUP_START_64), { 0, 0 }}, /* LDS_START */ {MSG_ORIG(MSG_SUP_ATEXIT_64), { 0, 0 }}, /* LDS_ATEXIT */ + {MSG_ORIG(MSG_SUP_OPEN_64), { 0, 0 }}, /* LDS_OPEN */ {MSG_ORIG(MSG_SUP_FILE_64), { 0, 0 }}, /* LDS_FILE */ {MSG_ORIG(MSG_SUP_INSEC_64), { 0, 0 }}, /* LDS_INSEC */ {MSG_ORIG(MSG_SUP_SEC_64), { 0, 0 }} /* LDS_SEC */ #else /* Elf32 */ {MSG_ORIG(MSG_SUP_START), { 0, 0 }}, /* LDS_START */ {MSG_ORIG(MSG_SUP_ATEXIT), { 0, 0 }}, /* LDS_ATEXIT */ + {MSG_ORIG(MSG_SUP_OPEN), { 0, 0 }}, /* LDS_OPEN */ {MSG_ORIG(MSG_SUP_FILE), { 0, 0 }}, /* LDS_FILE */ {MSG_ORIG(MSG_SUP_INSEC), { 0, 0 }}, /* LDS_INSEC */ {MSG_ORIG(MSG_SUP_SEC), { 0, 0 }} /* LDS_SEC */ @@ -143,6 +145,68 @@ } void +ld_sup_open(Ofl_desc *ofl, const char **opath, const char **ofile, int *ofd, + int flags, Elf **oelf, Elf *ref, size_t off, const Elf_Kind ekind) +{ + Func_list *flp; + Listnode *lnp; + const char *npath = *opath; + const char *nfile = *ofile; + Elf *nelf = *oelf; + int nfd = *ofd; + + for (LIST_TRAVERSE(&support[LDS_OPEN].sup_funcs, lnp, flp)) { + int _flags = 0; + + /* + * This interface was introduced in VERSION3. Only call this + * function for libraries reporting support for version 3 or + * above. + */ + if (flp->fl_version < LD_SUP_VERSION3) + continue; + + if (!(flags & FLG_IF_CMDLINE)) + _flags |= LD_SUP_DERIVED; + if (!(flags & FLG_IF_NEEDED)) + _flags |= LD_SUP_INHERITED; + if (flags & FLG_IF_EXTRACT) + _flags |= LD_SUP_EXTRACTED; + + /* + * If the present object is an extracted archive member, make + * sure the archive offset is reset so that the caller can + * obtain an ELF descriptor to the same member (an elf_begin() + * moves the offset to the next member). + */ + if (flags & FLG_IF_EXTRACT) + (void) elf_rand(ref, off); + + DBG_CALL(Dbg_support_action(ofl->ofl_lml, flp->fl_obj, + support[LDS_OPEN].sup_name, LDS_OPEN, *opath)); + (*flp->fl_fptr)(&npath, &nfile, &nfd, _flags, &nelf, ref, off, + ekind); + } + + /* + * If the file descriptor, ELF descriptor, or file names have been + * modified, then diagnose the differences and return the new data. + * As a basic test, make sure the support library hasn't nulled out + * data ld(1) will try and dereference. + */ + if ((npath != *opath) || (nfd != *ofd) || (nelf != *oelf)) { + Dbg_file_modified(ofl->ofl_lml, flp->fl_obj, *opath, npath, + *ofd, nfd, *oelf, nelf); + if (npath) + *opath = npath; + if (nfile) + *ofile = nfile; + *ofd = nfd; + *oelf = nelf; + } +} + +void ld_sup_file(Ofl_desc *ofl, const char *ifile, const Elf_Kind ekind, int flags, Elf *elf) { @@ -203,8 +267,8 @@ * return the new section header. */ if (nshdr != *oshdr) { - Dbg_shdr_modified(ofl->ofl_lml, ifl->ifl_ehdr->e_machine, - *oshdr, nshdr, sname); + Dbg_shdr_modified(ofl->ofl_lml, flp->fl_obj, + ifl->ifl_ehdr->e_machine, *oshdr, nshdr, sname); *oshdr = nshdr; } return (0);
--- a/usr/src/cmd/sgs/libld/common/update.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/libld/common/update.c Tue Oct 24 09:55:12 2006 -0700 @@ -3200,8 +3200,8 @@ /* * Adjust the address offset and p_align if needed. */ - if (!((ofl->ofl_flags1 & FLG_OF1_VADDR) || - (ofl->ofl_dtflags_1 & DF_1_NOHDR))) { + if (((sgp->sg_flags & FLG_SG_VADDR) == 0) && + ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0)) { if (phdr->p_align != 0) vaddr += phdr->p_offset % phdr->p_align; else
--- a/usr/src/cmd/sgs/liblddbg/common/files.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/files.c Tue Oct 24 09:55:12 2006 -0700 @@ -681,3 +681,37 @@ else dbg_print(lml, MSG_INTL(MSG_FIL_SKIP_2), nname); } + +void +Dbg_file_modified(Lm_list *lml, const char *obj, const char *oname, + const char *nname, int ofd, int nfd, Elf *oelf, Elf *nelf) +{ + const char *str; + + if (DBG_NOTCLASS(DBG_C_FILES | DBG_C_SUPPORT)) + return; + if (DBG_NOTDETAIL()) + return; + + Dbg_util_nl(lml, DBG_NL_STD); + dbg_print(lml, MSG_INTL(MSG_FIL_MODIFIED), oname, obj); + + if (nname != oname) + dbg_print(lml, MSG_INTL(MSG_FIL_NAMECHANGE), nname); + if (nfd != ofd) { + if (nfd == -1) + str = MSG_INTL(MSG_FIL_IGNORE); + else + str = MSG_ORIG(MSG_STR_EMPTY); + dbg_print(lml, MSG_INTL(MSG_FIL_FDCHANGE), ofd, nfd, str); + } + if (nelf != oelf) { + if (nelf == 0) + str = MSG_INTL(MSG_FIL_IGNORE); + else + str = MSG_ORIG(MSG_STR_EMPTY); + dbg_print(lml, MSG_INTL(MSG_FIL_ELFCHANGE), EC_NATPTR(oelf), + EC_NATPTR(nelf), str); + } + Dbg_util_nl(lml, DBG_NL_STD); +}
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg Tue Oct 24 09:55:12 2006 -0700 @@ -435,6 +435,12 @@ @ MSG_FIL_CONFIG_ERR_5 "incompatible ELF class, byte order, or machine \ architecture" +@ MSG_FIL_MODIFIED "file=%s; open modified by support library: %s" +@ MSG_FIL_NAMECHANGE " name changed to: %s" +@ MSG_FIL_FDCHANGE " file descriptor changed from: %d to: %d %s" +@ MSG_FIL_ELFCHANGE " ELF descriptor changed from: 0x%llx to: 0x%llx %s" +@ MSG_FIL_IGNORE " (file will be ignored)" + @ MSG_CNTL_TITLE "control list processing complete: moving lmco 0x%llx \ to lmco 0x%llx" @@ -522,9 +528,10 @@ # Section header messages -@ MSG_SHD_MODIFIED "section=%s; section header modified by support library" -@ MSG_SHD_ORIG " original:" -@ MSG_SHD_NEW " new:" +@ MSG_SHD_MODIFIED "section=%s; section header modified by support \ + library: %s" +@ MSG_SHD_ORIG " original:" +@ MSG_SHD_NEW " new:" # Section messages
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg Tue Oct 24 09:55:12 2006 -0700 @@ -129,6 +129,10 @@ void Dbg64_file_ldso(Rt_map *, char **, auxv_t *, const char *, Aliste); void Dbg32_file_mode_promote(Rt_map *, int); void Dbg64_file_mode_promote(Rt_map *, int); +void Dbg32_file_modified(Lm_list *, const char *, const char *, const char *, + int, int, Elf *, Elf *); +void Dbg64_file_modified(Lm_list *, const char *, const char *, const char *, + int, int, Elf *, Elf *); void Dbg32_file_needed(Rt_map *, const char *); void Dbg64_file_needed(Rt_map *, const char *); void Dbg32_file_output(Ofl_desc *); @@ -297,8 +301,10 @@ void Dbg32_seg_title(Lm_list *); void Dbg64_seg_title(Lm_list *); -void Dbg32_shdr_modified(Lm_list *, Half, Shdr *, Shdr *, const char *); -void Dbg64_shdr_modified(Lm_list *, Half, Shdr *, Shdr *, const char *); +void Dbg32_shdr_modified(Lm_list *, const char *, Half, Shdr *, Shdr *, + const char *); +void Dbg64_shdr_modified(Lm_list *, const char *, Half, Shdr *, Shdr *, + const char *); void Dbg32_statistics_ar(Ofl_desc *); void Dbg64_statistics_ar(Ofl_desc *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers Tue Oct 24 09:55:12 2006 -0700 @@ -38,7 +38,7 @@ # Policy for Shared Library Version Names and Interface Definitions -SUNWprivate_4.53 { +SUNWprivate_4.54 { global: dbg_desc = NODIRECT; # interposed - ld.so.1(1) dbg_print = NODIRECT; # interposed - ld(1) and ld.so.1(1) @@ -131,6 +131,8 @@ Dbg64_file_ldso; Dbg32_file_mode_promote; Dbg64_file_mode_promote; + Dbg32_file_modified; + Dbg64_file_modified; Dbg32_file_needed; Dbg64_file_needed; Dbg32_file_output;
--- a/usr/src/cmd/sgs/liblddbg/common/shdr.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/shdr.c Tue Oct 24 09:55:12 2006 -0700 @@ -48,16 +48,16 @@ } void -Dbg_shdr_modified(Lm_list *lml, Half mach, Shdr *oshdr, Shdr *nshdr, - const char *name) +Dbg_shdr_modified(Lm_list *lml, const char *obj, Half mach, Shdr *oshdr, + Shdr *nshdr, const char *name) { - if (DBG_NOTCLASS(DBG_C_SECTIONS)) + if (DBG_NOTCLASS(DBG_C_SECTIONS | DBG_C_SUPPORT)) return; if (DBG_NOTDETAIL()) return; Dbg_util_nl(lml, DBG_NL_STD); - dbg_print(lml, MSG_INTL(MSG_SHD_MODIFIED), name); + dbg_print(lml, MSG_INTL(MSG_SHD_MODIFIED), name, obj); dbg_print(lml, MSG_INTL(MSG_SHD_ORIG)); Elf_shdr(lml, mach, oshdr);
--- a/usr/src/cmd/sgs/liblddbg/common/support.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/liblddbg/common/support.c Tue Oct 24 09:55:12 2006 -0700 @@ -69,7 +69,7 @@ if (ndx == LDS_START) str = MSG_INTL(MSG_SUP_OUTFILE); - else if (ndx == LDS_FILE) + else if ((ndx == LDS_OPEN) || (ndx == LDS_FILE)) str = MSG_INTL(MSG_SUP_INFILE); else if (ndx == LDS_INSEC) str = MSG_INTL(MSG_SUP_INSEC);
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README Tue Oct 24 09:55:12 2006 -0700 @@ -1136,3 +1136,10 @@ 6475375 symbol search optimization to reduce rescans 6475497 elfdump(1) is misreporting sh_link 6477132 ld.so.1: memory leak when running set*id application +6479848 Enhancements to the linker support interface needed. (D) + PSARC/2006/595 link-editor support library interface - ld_open() +6482058 lari(1) could be faster, and handle per-symbol filters better +6482974 defining virtual address of text segment can result in an invalid data + segment +6476734 crle(1m) "-l" as described fails system, crle cores trying to fix + /a/var/ld/ld.config in failsafe
--- a/usr/src/cmd/sgs/rtld/common/object.c Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/cmd/sgs/rtld/common/object.c Tue Oct 24 09:55:12 2006 -0700 @@ -144,7 +144,7 @@ * Proceed to process the input file. */ DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD)); - if (ld_process_open(name, name, fd, (Ofl_desc *)olmp->rt_priv, + if (ld_process_open(name, name, &fd, (Ofl_desc *)olmp->rt_priv, NULL, &rej) == (Ifl_desc *)S_ERROR) return (0); return (olmp);
--- a/usr/src/head/link.h Tue Oct 24 01:13:19 2006 -0700 +++ b/usr/src/head/link.h Tue Oct 24 09:55:12 2006 -0700 @@ -46,18 +46,23 @@ */ #ifdef __STDC__ extern uint_t ld_version(uint_t); +extern void ld_input_done(uint_t *); + extern void ld_start(const char *, const Elf32_Half, const char *); extern void ld_atexit(int); +extern void ld_open(const char **, const char **, int *, int, Elf **, + Elf *, size_t, const Elf_Kind); extern void ld_file(const char *, const Elf_Kind, int, Elf *); extern void ld_input_section(const char *, Elf32_Shdr **, Elf32_Word, Elf_Data *, Elf *, uint_t *); -extern void ld_input_done(uint_t *); extern void ld_section(const char *, Elf32_Shdr *, Elf32_Word, Elf_Data *, Elf *); #if defined(_LP64) || defined(_LONGLONG_TYPE) extern void ld_start64(const char *, const Elf64_Half, const char *); extern void ld_atexit64(int); +extern void ld_open64(const char **, const char **, int *, int, Elf **, + Elf *, size_t, const Elf_Kind); extern void ld_file64(const char *, const Elf_Kind, int, Elf *); extern void ld_input_section64(const char *, Elf64_Shdr **, Elf64_Word, Elf_Data *, Elf *, uint_t *); @@ -67,39 +72,46 @@ #endif /* (defined(_LP64) || defined(_LONGLONG_TYPE) */ #else extern void ld_version(); +extern void ld_input_done(); + extern void ld_start(); extern void ld_atexit(); +extern void ld_open(); extern void ld_file(); extern void ld_input_section(); -extern void ld_input_done(); extern void ld_section(); #if defined(_LP64) || defined(_LONGLONG_TYPE) extern void ld_start64(); extern void ld_atexit64(); +extern void ld_open64(); extern void ld_file64(); +extern void ld_input_section64(); extern void ld_section64(); #endif /* (defined(_LP64) || defined(_LONGLONG_TYPE) */ #endif /* __STDC__ */ /* - * ld_version() version values + * ld_version() version values. */ #define LD_SUP_VNONE 0 #define LD_SUP_VERSION1 1 #define LD_SUP_VERSION2 2 -#define LD_SUP_VCURRENT LD_SUP_VERSION2 - +#define LD_SUP_VERSION3 3 +#define LD_SUP_VCURRENT LD_SUP_VERSION3 /* - * flags passed to ld support calls + * Flags passed to ld support calls. */ #define LD_SUP_DERIVED 0x1 /* derived filename */ #define LD_SUP_INHERITED 0x2 /* file inherited from .so DT_NEEDED */ #define LD_SUP_EXTRACTED 0x4 /* file extracted from archive */ #endif +/* + * Runtime link-map identifiers. + */ #define LM_ID_BASE 0x00 #define LM_ID_LDSO 0x01 #define LM_ID_BRAND 0x02 /* marks branded objs in rd_loadobj_t */ @@ -109,9 +121,8 @@ #define LM_ID_NEWLM 0xff /* create a new link-map */ - /* - * Run-Time Link-Edit Auditing + * Runtime Link-Edit Auditing. */ #define LAV_NONE 0 #define LAV_VERSION1 1