summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdw/libdw.h1
-rw-r--r--libelf/libelfP.h17
-rw-r--r--src/ChangeLog14
-rw-r--r--src/addr2line.c3
-rw-r--r--src/ld.c17
-rw-r--r--src/ld.h10
-rw-r--r--src/ldgeneric.c9
-rw-r--r--src/ldscript.y30
8 files changed, 76 insertions, 25 deletions
diff --git a/libdw/libdw.h b/libdw/libdw.h
index 0758a38d..424c354e 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -1,6 +1,7 @@
/* Interfaces for libdw.
Copyright (C) 2002, 2004, 2005, 2006 Red Hat, Inc.
This file is part of Red Hat elfutils.
+ Contributed by Ulrich Drepper <[email protected]>, 2002.
Red Hat elfutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
index 54158aeb..ed6b5f7f 100644
--- a/libelf/libelfP.h
+++ b/libelf/libelfP.h
@@ -1,5 +1,5 @@
/* Internal interfaces for libelf.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 Red Hat, Inc.
This file is part of Red Hat elfutils.
Contributed by Ulrich Drepper <[email protected]>, 1998.
@@ -546,8 +546,9 @@ extern uint32_t __libelf_crc32 (uint32_t crc, unsigned char *buf, size_t len)
/* We often have to update a flag iff a value changed. Make this
- convenient. */
-#define update_if_changed(var, exp, flag) \
+ convenient. None of the parameters must have a side effect. */
+#ifdef __GNUC__
+# define update_if_changed(var, exp, flag) \
do { \
__typeof__ (var) *_var = &(var); \
__typeof__ (exp) _exp = (exp); \
@@ -557,5 +558,15 @@ extern uint32_t __libelf_crc32 (uint32_t crc, unsigned char *buf, size_t len)
(flag) |= ELF_F_DIRTY; \
} \
} while (0)
+#else
+# define update_if_changed(var, exp, flag) \
+ do { \
+ if ((var) != (exp)) \
+ { \
+ (var) = (exp); \
+ (flag) |= ELF_F_DIRTY; \
+ } \
+ } while (0)
+#endif
#endif /* libelfP.h */
diff --git a/src/ChangeLog b/src/ChangeLog
index 77f9867b..dc068b4f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,7 +1,13 @@
-2006-05-28 Ulrich Drepper <[email protected]>
-
- * addr2line.c (print_dwarf_function): Use unsigned type for lineno
- and colno.
+2006-05-31 Ulrich Drepper <[email protected]>
+
+ * ld.c: Recognize --as-needed and --no-as-needed options.
+ * ld.h (struct usedfile): Add as_needed field.
+ (struct ld_state): Likewise.
+ * ldgeneric.c (ld_handle_filename_list): Copy as_needed flag from
+ the list.
+ * ldscript.y (filename_id_list): Split to correctly parse all
+ combinations.
+ (mark_as_needed): Fix loop.
2006-05-27 Ulrich Drepper <[email protected]>
diff --git a/src/addr2line.c b/src/addr2line.c
index 1729058e..bc0ea803 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -258,8 +258,7 @@ print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
&attr_mem), &val) == 0)
{
const char *file = dwarf_filesrc (files, val, NULL, NULL);
- unsigned int lineno = 0;
- unsigned int colno = 0;
+ int lineno = 0, colno = 0;
if (dwarf_formudata (dwarf_attr (&scopes[i],
DW_AT_call_line,
&attr_mem), &val) == 0)
diff --git a/src/ld.c b/src/ld.c
index 110072f9..99190df9 100644
--- a/src/ld.c
+++ b/src/ld.c
@@ -71,6 +71,8 @@ enum
ARGP_no_gc_sections,
ARGP_no_undefined,
ARGP_conserve,
+ ARGP_as_needed,
+ ARGP_no_as_needed,
#if YYDEBUG
ARGP_yydebug,
#endif
@@ -192,6 +194,11 @@ Default rules of extracting from archive; weak references are not enough."),
N_("Add/suppress addition indentifying link-editor to .comment section"),
0 },
+ { "as-needed", ARGP_as_needed, NULL, 0,
+ N_("Only set DT_NEEDED for following dynamic libs if actually used"), 0 },
+ { "no-as-needed", ARGP_no_as_needed, NULL, 0,
+ N_("Always set DT_NEEDED for following dynamic libs"), 0 },
+
#if YYDEBUG
{ "yydebug", ARGP_yydebug, NULL, 0,
N_("Select to get parser debug information"), 0 },
@@ -636,6 +643,8 @@ parse_opt_1st (int key, char *arg,
case 'O':
case ARGP_whole_archive:
case ARGP_no_whole_archive:
+ case ARGP_as_needed:
+ case ARGP_no_as_needed:
case 'L':
case '(':
case ')':
@@ -732,6 +741,13 @@ parse_opt_2nd (int key, char *arg,
ld_state.extract_rule = defaultextract;
break;
+ case ARGP_as_needed:
+ ld_state.as_needed = true;
+ break;
+ case ARGP_no_as_needed:
+ ld_state.as_needed = false;
+ break;
+
case ARGP_static:
case ARGP_dynamic:
/* Enable/disable use for DSOs. */
@@ -1107,6 +1123,7 @@ ld_new_inputfile (const char *fname, enum file_type type)
newfile->soname = newfile->fname = newfile->rfname = fname;
newfile->file_type = type;
newfile->extract_rule = ld_state.extract_rule;
+ newfile->as_needed = ld_state.as_needed;
newfile->lazyload = ld_state.lazyload;
newfile->status = not_opened;
diff --git a/src/ld.h b/src/ld.h
index 3de257ca..47354cbe 100644
--- a/src/ld.h
+++ b/src/ld.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2005, 2006 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2001.
@@ -115,6 +115,10 @@ struct usedfiles
used in a reference. */
bool used;
+ /* True when file should be added to DT_NEEDED list only when
+ directly referenced. */
+ bool as_needed;
+
/* If nonzero this is the archive sequence number which can be used to
determine whether back refernces from -( -) or GROUP statements
have to be followed. */
@@ -791,6 +795,10 @@ struct ld_state
/* If true static linking is requested. */
bool statically;
+ /* If true, add DT_NEEDED entries for following files if they are
+ needed. */
+ bool as_needed;
+
/* How to extract elements from archives. */
enum extract_rule extract_rule;
diff --git a/src/ldgeneric.c b/src/ldgeneric.c
index c4c18a96..e0621d01 100644
--- a/src/ldgeneric.c
+++ b/src/ldgeneric.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2001.
@@ -1534,8 +1534,11 @@ ld_handle_filename_list (struct filename_list *fnames)
curp = runp->real = ld_new_inputfile (runp->name, relocatable_file_type);
/* Set flags for group handling. */
- runp->real->group_start = runp->group_start;
- runp->real->group_end = runp->group_end;
+ curp->group_start = runp->group_start;
+ curp->group_end = runp->group_end;
+
+ /* Set as-needed flag from the file, not the command line. */
+ curp->as_needed = runp->as_needed;
/* Read the file and everything else which comes up, including
handling groups. */
diff --git a/src/ldscript.y b/src/ldscript.y
index 7311164c..764b4157 100644
--- a/src/ldscript.y
+++ b/src/ldscript.y
@@ -1,6 +1,6 @@
%{
/* Parser for linker scripts.
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <[email protected]>, 2001.
@@ -128,6 +128,7 @@ extern int yylex (void);
%type <output_rule> outputsections
%type <assignment> assignment
%type <filename_list> filename_id_list
+%type <filename_list> filename_id_listelem
%type <version> versionlist
%type <version> version
%type <version> version_stmt_list
@@ -358,7 +359,20 @@ expr: kALIGN '(' expr ')'
{ $$ = new_expr (exp_pagesize); }
;
-filename_id_list: kGROUP '(' filename_id_list ')'
+filename_id_list: filename_id_list comma_opt filename_id_listelem
+ {
+ $3->next = $1->next;
+ $$ = $1->next = $3;
+ }
+ | filename_id_listelem
+ { $$ = $1; }
+ ;
+
+comma_opt: ','
+ |
+ ;
+
+filename_id_listelem: kGROUP '(' filename_id_list ')'
{
/* First little optimization. If there is only one
file in the group don't do anything. */
@@ -371,19 +385,10 @@ filename_id_list: kGROUP '(' filename_id_list ')'
}
| kAS_NEEDED '(' filename_id_list ')'
{ $$ = mark_as_needed ($3); }
- | filename_id_list comma_opt filename_id
- {
- struct filename_list *newp = new_filename_listelem ($3);
- newp->next = $1->next;
- $$ = $1->next = newp;
- }
| filename_id
{ $$ = new_filename_listelem ($1); }
;
-comma_opt: ','
- |
- ;
versionlist: versionlist version
{
@@ -579,11 +584,12 @@ static struct filename_list *
mark_as_needed (struct filename_list *listp)
{
struct filename_list *runp = listp;
- while (runp != NULL)
+ do
{
runp->as_needed = true;
runp = runp->next;
}
+ while (runp != listp);
return listp;
}