Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.145
diff -u -p -r1.145 bfd-in.h
--- bfd/bfd-in.h	26 May 2009 14:12:02 -0000	1.145
+++ bfd/bfd-in.h	28 Aug 2009 19:21:38 -0000
@@ -618,7 +618,9 @@ enum dynamic_lib_link_class {
   DYN_AS_NEEDED = 1,
   DYN_DT_NEEDED = 2,
   DYN_NO_ADD_NEEDED = 4,
-  DYN_NO_NEEDED = 8
+  DYN_NO_NEEDED = 8,
+  DYN_DT_AUDIT = 16,
+  DYN_DT_DEPAUDIT = 32
 };
 
 enum notice_asneeded_action {
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.491
diff -u -p -r1.491 bfd-in2.h
--- bfd/bfd-in2.h	6 Aug 2009 17:37:59 -0000	1.491
+++ bfd/bfd-in2.h	28 Aug 2009 19:21:38 -0000
@@ -625,7 +625,9 @@ enum dynamic_lib_link_class {
   DYN_AS_NEEDED = 1,
   DYN_DT_NEEDED = 2,
   DYN_NO_ADD_NEEDED = 4,
-  DYN_NO_NEEDED = 8
+  DYN_NO_NEEDED = 8,
+  DYN_DT_AUDIT = 16,
+  DYN_DT_DEPAUDIT = 32
 };
 
 enum notice_asneeded_action {
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.352
diff -u -p -r1.352 elflink.c
--- bfd/elflink.c	11 Aug 2009 02:21:34 -0000	1.352
+++ bfd/elflink.c	28 Aug 2009 19:21:38 -0000
@@ -3086,7 +3086,8 @@ _bfd_elf_add_dynamic_entry (struct bfd_l
    1 if a DT_NEEDED tag already exists, and 0 on success.  */
 
 static int
-elf_add_dt_needed_tag (bfd *abfd,
+elf_add_dt_needed_like_tag (bfd *abfd,
+		       unsigned int needed_type,
 		       struct bfd_link_info *info,
 		       const char *soname,
 		       bfd_boolean do_it)
@@ -3120,7 +3121,7 @@ elf_add_dt_needed_tag (bfd *abfd,
 	    Elf_Internal_Dyn dyn;
 
 	    bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
-	    if (dyn.d_tag == DT_NEEDED
+	    if (dyn.d_tag == needed_type 
 		&& dyn.d_un.d_val == strindex)
 	      {
 		_bfd_elf_strtab_delref (hash_table->dynstr, strindex);
@@ -3134,7 +3135,8 @@ elf_add_dt_needed_tag (bfd *abfd,
       if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
 	return -1;
 
-      if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+     
+      if (!_bfd_elf_add_dynamic_entry (info, needed_type, strindex))
 	return -1;
     }
   else
@@ -3388,6 +3390,12 @@ elf_link_add_object_symbols (bfd *abfd, 
   long old_dynsymcount = 0;
   size_t tabsize = 0;
   size_t hashsize = 0;
+  unsigned int needed_type = DT_NEEDED;
+
+  if (elf_dyn_lib_class(abfd) & DYN_DT_AUDIT)
+    needed_type = DT_AUDIT;
+  else if (elf_dyn_lib_class(abfd) & DYN_DT_DEPAUDIT)
+    needed_type = DT_DEPAUDIT;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
@@ -3695,7 +3703,9 @@ error_free_dyn:
 	 will need to know it.  */
       elf_dt_name (abfd) = soname;
 
-      ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
+
+      ret = elf_add_dt_needed_like_tag (abfd, needed_type, info, soname,
+					add_needed);
       if (ret < 0)
 	goto error_return;
 
@@ -4444,7 +4454,9 @@ error_free_dyn:
 	      elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED;
 
 	      add_needed = TRUE;
-	      ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
+
+	      ret = elf_add_dt_needed_like_tag (abfd, needed_type, info, soname,
+						add_needed);
 	      if (ret < 0)
 		goto error_free_vers;
 
Index: ld/ldfile.c
===================================================================
RCS file: /cvs/src/src/ld/ldfile.c,v
retrieving revision 1.52
diff -u -p -r1.52 ldfile.c
--- ld/ldfile.c	14 Apr 2009 03:17:21 -0000	1.52
+++ ld/ldfile.c	28 Aug 2009 19:21:39 -0000
@@ -371,7 +371,12 @@ ldfile_open_file (lang_input_statement_t
   if (entry->the_bfd != NULL)
     return;
 
-  if (! entry->search_dirs_flag)
+  if (entry->is_audit || entry->is_depaudit)
+    {
+      ldemul_open_dynamic_archive(entry->filename, NULL, entry);
+      return; 
+    }
+  else if (! entry->search_dirs_flag)
     {
       if (ldfile_try_open_bfd (entry->filename, entry))
 	return;
Index: ld/ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.59
diff -u -p -r1.59 ldgram.y
--- ld/ldgram.y	2 Mar 2009 17:27:35 -0000	1.59
+++ ld/ldgram.y	28 Aug 2009 19:21:39 -0000
@@ -97,7 +97,7 @@ static int error_index;
 %type <cname> wildcard_name
 %type <wildcard> wildcard_spec
 %token <bigint> INT
-%token <name> NAME LNAME
+%token <name> NAME LNAME AUDIT_NAME DEPAUDIT_NAME
 %type <integer> length
 %type <phdr> phdr_qualifiers
 %type <nocrossref> nocrossref_list
@@ -376,6 +376,24 @@ input_list:
 	|	input_list LNAME
 		{ lang_add_input_file($2,lang_input_file_is_l_enum,
 				 (char *)NULL); }
+	|	AUDIT_NAME
+		{ lang_add_input_file($1,lang_input_file_is_audit_enum,
+				 (char *)NULL); }
+	|	input_list ',' AUDIT_NAME
+		{ lang_add_input_file($3,lang_input_file_is_audit_enum,
+				 (char *)NULL); }
+	|	input_list AUDIT_NAME
+		{ lang_add_input_file($2,lang_input_file_is_audit_enum,
+				 (char *)NULL); }
+	|	DEPAUDIT_NAME
+		{ lang_add_input_file($1,lang_input_file_is_depaudit_enum,
+				 (char *)NULL); }
+	|	input_list ',' DEPAUDIT_NAME
+		{ lang_add_input_file($3,lang_input_file_is_depaudit_enum,
+				 (char *)NULL); }
+	|	input_list DEPAUDIT_NAME
+		{ lang_add_input_file($2,lang_input_file_is_depaudit_enum,
+				 (char *)NULL); }
 	|	AS_NEEDED '('
 		  { $<integer>$ = as_needed; as_needed = TRUE; }
 		     input_list ')'
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.315
diff -u -p -r1.315 ldlang.c
--- ld/ldlang.c	12 Aug 2009 12:40:55 -0000	1.315
+++ ld/ldlang.c	28 Aug 2009 19:21:39 -0000
@@ -1004,6 +1004,9 @@ new_afile (const char *name,
       p->local_sym_name = name;
       p->just_syms_flag = TRUE;
       p->search_dirs_flag = FALSE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
       break;
     case lang_input_file_is_fake_enum:
       p->filename = name;
@@ -1012,6 +1015,9 @@ new_afile (const char *name,
       p->local_sym_name = name;
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = FALSE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
       break;
     case lang_input_file_is_l_enum:
       p->is_archive = TRUE;
@@ -1020,6 +1026,9 @@ new_afile (const char *name,
       p->local_sym_name = concat ("-l", name, (const char *) NULL);
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = TRUE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
       break;
     case lang_input_file_is_marker_enum:
       p->filename = name;
@@ -1028,6 +1037,9 @@ new_afile (const char *name,
       p->local_sym_name = name;
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = TRUE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
       break;
     case lang_input_file_is_search_file_enum:
       p->sysrooted = ldlang_sysrooted_script;
@@ -1037,6 +1049,9 @@ new_afile (const char *name,
       p->local_sym_name = name;
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = TRUE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
       break;
     case lang_input_file_is_file_enum:
       p->filename = name;
@@ -1045,6 +1060,31 @@ new_afile (const char *name,
       p->local_sym_name = name;
       p->just_syms_flag = FALSE;
       p->search_dirs_flag = FALSE;
+      p->is_audit = FALSE;
+      p->is_depaudit = FALSE;
+      p->add_needed = add_needed;
+      break;
+    case lang_input_file_is_audit_enum:
+      p->is_archive = TRUE;
+      p->filename = name;
+      p->real = TRUE;
+      p->local_sym_name = concat ("-p", name, (const char *) NULL);
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = FALSE;
+      p->is_audit = TRUE;
+      p->is_depaudit = FALSE;
+      p->add_needed = FALSE;
+      break;
+    case lang_input_file_is_depaudit_enum:
+      p->is_archive = TRUE;
+      p->filename = name;
+      p->real = TRUE;
+      p->local_sym_name = concat ("-p", name, (const char *) NULL);
+      p->just_syms_flag = FALSE;
+      p->search_dirs_flag = FALSE;
+      p->is_audit = FALSE;
+      p->is_depaudit = TRUE;
+      p->add_needed = FALSE;
       break;
     default:
       FAIL ();
@@ -1053,7 +1093,6 @@ new_afile (const char *name,
   p->next_real_file = NULL;
   p->next = NULL;
   p->dynamic = config.dynamic_link;
-  p->add_needed = add_needed;
   p->as_needed = as_needed;
   p->whole_archive = whole_archive;
   p->loaded = FALSE;
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.84
diff -u -p -r1.84 ldlang.h
--- ld/ldlang.h	10 Aug 2009 07:50:56 -0000	1.84
+++ ld/ldlang.h	28 Aug 2009 19:21:39 -0000
@@ -32,7 +32,9 @@ typedef enum
   lang_input_file_is_marker_enum,
   lang_input_file_is_fake_enum,
   lang_input_file_is_search_file_enum,
-  lang_input_file_is_file_enum
+  lang_input_file_is_file_enum,
+  lang_input_file_is_audit_enum,
+  lang_input_file_is_depaudit_enum,
 } lang_input_file_enum_type;
 
 struct _fill_type
@@ -280,6 +282,13 @@ typedef struct lang_input_statement_stru
   unsigned int loaded : 1;
 
   unsigned int real : 1;
+
+  /* Whether this entry represents a DT_AUDIT entry */
+  unsigned int is_audit : 1;
+
+  /* Whether this entry represents a DT_DEPAUDIT entry */
+  unsigned int is_depaudit : 1;
+
 } lang_input_statement_type;
 
 typedef struct
Index: ld/ldlex.l
===================================================================
RCS file: /cvs/src/src/ld/ldlex.l,v
retrieving revision 1.42
diff -u -p -r1.42 ldlex.l
--- ld/ldlex.l	2 Mar 2009 17:27:35 -0000	1.42
+++ ld/ldlex.l	28 Aug 2009 19:21:39 -0000
@@ -372,6 +372,14 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
 				  yylval.name = xstrdup (yytext + 2);
 				  return LNAME;
 				}
+<BOTH>"-p"{FILENAMECHAR}+ {
+				  yylval.name = xstrdup (yytext + 2);
+				  return AUDIT_NAME;
+				}
+<BOTH>"-P"{FILENAMECHAR}+ {
+				  yylval.name = xstrdup (yytext + 2);
+				  return DEPAUDIT_NAME;
+				}
 <EXPRESSION>{FILENAMECHAR1}{NOCFILENAMECHAR}*	{
 				 yylval.name = xstrdup (yytext);
 				  return NAME;
@@ -380,6 +388,14 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
 				  yylval.name = xstrdup (yytext + 2);
 				  return LNAME;
 				}
+<EXPRESSION>"-p"{NOCFILENAMECHAR}+ {
+				  yylval.name = xstrdup (yytext + 2);
+				  return AUDIT_NAME;
+				}
+<EXPRESSION>"-P"{NOCFILENAMECHAR}+ {
+				  yylval.name = xstrdup (yytext + 2);
+				  return DEPAUDIT_NAME;
+				}
 <SCRIPT>{WILDCHAR}* {
 		/* Annoyingly, this pattern can match comments, and we have
 		   longest match issues to consider.  So if the first two
Index: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.112
diff -u -p -r1.112 lexsup.c
--- ld/lexsup.c	29 Apr 2009 17:24:26 -0000	1.112
+++ ld/lexsup.c	28 Aug 2009 19:21:39 -0000
@@ -268,6 +268,10 @@ static const struct ld_option ld_options
     'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
   { {NULL, required_argument, NULL, '\0'},
     'O', NULL, N_("Optimize output file"), ONE_DASH },
+  { {"audit", required_argument, NULL, 'p'},
+    'p', N_("AUDITLIB"), N_("Use AUDITLIB for rtld auditing."), TWO_DASHES },
+  { {"depaudit", required_argument, NULL, 'P'},
+    'P', N_("AUDITLIB"), N_("Use AUDITLIB for rtld dependency auditing."), TWO_DASHES },
   { {"Qy", no_argument, NULL, OPTION_IGNORE},
     '\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
   { {"emit-relocs", no_argument, NULL, 'q'},
@@ -885,6 +889,12 @@ parse_args (unsigned argc, char **argv)
 	case 'l':
 	  lang_add_input_file (optarg, lang_input_file_is_l_enum, NULL);
 	  break;
+	case 'p':
+	  lang_add_input_file (optarg, lang_input_file_is_audit_enum, NULL);
+	  break;
+	case 'P':
+	  lang_add_input_file (optarg, lang_input_file_is_depaudit_enum, NULL);
+	  break;
 	case 'M':
 	  config.map_filename = "-";
 	  break;
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.199
diff -u -p -r1.199 elf32.em
--- ld/emultempl/elf32.em	26 Aug 2009 13:08:07 -0000	1.199
+++ ld/emultempl/elf32.em	28 Aug 2009 19:21:39 -0000
@@ -127,6 +127,12 @@ gld${EMULATION_NAME}_load_symbols (lang_
   if (!entry->add_needed)
     class |= DYN_NO_ADD_NEEDED;
 
+  if (entry->is_audit)
+    class |= DYN_DT_AUDIT;
+  
+  if (entry->is_depaudit)
+    class |= DYN_DT_DEPAUDIT;
+
   if (entry->just_syms_flag
       && (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) != 0)
     einfo (_("%P%F: --just-symbols may not be used on DSO: %B\n"),
@@ -1510,6 +1516,21 @@ gld${EMULATION_NAME}_open_dynamic_archiv
 
   filename = entry->filename;
 
+  if (entry->is_audit || entry->is_depaudit)
+    {
+
+      if (ldfile_try_open_bfd (entry->filename, entry)
+      	  && bfd_check_format (entry->the_bfd, bfd_object)
+          && (entry->the_bfd->flags & DYNAMIC) != 0)
+	{
+	  return TRUE;
+	}
+      return FALSE;
+    }
+
+  if (search == NULL)
+    return FALSE; /* assertion? */
+
   /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION
      is defined, but it does not seem worth the headache to optimize
      away those two bytes of space.  */
Index: ld/testsuite/ld-elf/audit.exp
===================================================================
RCS file: ld/testsuite/ld-elf/audit.exp
diff -N ld/testsuite/ld-elf/audit.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elf/audit.exp	28 Aug 2009 19:21:39 -0000
@@ -0,0 +1,51 @@
+# Expect script for various ELF tests.
+#   Copyright 2009 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Exclude non-ELF targets.
+
+if ![is_elf_format] {
+    return
+}
+
+# The following tests require running the executable generated by ld.
+if ![isnative] {
+    return
+}
+
+# Check if compiler works
+if { [which $CC] == 0 } {
+    return
+}
+
+set build_tests {
+  {"Build audit.so"
+   "-shared" "-fPIC"
+   {auditlib.c} {} "audit.so"}
+  {"Run with -paudit.so"
+     "-Wl,-ptmpdir/audit.so" ""
+     {main.c} {{"readelf" {"-d"} "audit.rd"}} "audit.out"}
+  {"Run with -Paudit.so"
+     "-Wl,-Ptmpdir/audit.so" ""
+     {main.c} {{"readelf" {-d} "depaudit.rd"}} "depaudit.out"}
+}
+
+run_cc_link_tests $build_tests
+
Index: ld/testsuite/ld-elf/audit.rd
===================================================================
RCS file: ld/testsuite/ld-elf/audit.rd
diff -N ld/testsuite/ld-elf/audit.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elf/audit.rd	28 Aug 2009 19:21:39 -0000
@@ -0,0 +1 @@
+.*Audit library: \[tmpdir/audit.so\].*
Index: ld/testsuite/ld-elf/auditlib.c
===================================================================
RCS file: ld/testsuite/ld-elf/auditlib.c
diff -N ld/testsuite/ld-elf/auditlib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elf/auditlib.c	28 Aug 2009 19:21:39 -0000
@@ -0,0 +1,14 @@
+#define _GNU_SOURCE
+#include <link.h>
+
+unsigned int la_version(unsigned int version)
+{
+  return version;
+}
+
+char *
+la_objsearch(const char *name, uintptr_t *cookie, unsigned int flag)
+{
+  return (char *)name;
+}
+
Index: ld/testsuite/ld-elf/depaudit.rd
===================================================================
RCS file: ld/testsuite/ld-elf/depaudit.rd
diff -N ld/testsuite/ld-elf/depaudit.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-elf/depaudit.rd	28 Aug 2009 19:21:39 -0000
@@ -0,0 +1 @@
+.*Dependency audit library: \[tmpdir/audit.so\].*
