Discussion:
How to get the default linker script used by gcc?
Pan ruochen
2009-05-11 05:34:45 UTC
Permalink
Hi All,

When I use gcc to build an executable like this
gcc a.c
How I can get the linker used by LD for that executable?
Is there any option for this purpose? My LD version is 2.17.50

Best Regards
PRC
May 11,2009
M R Swami Reddy
2009-05-11 05:44:38 UTC
Permalink
Pass -verbose option to linker, will show you the default linker script file info.
gcc a.c -Wl,-verbose
Best Regards,
Swami
Hi All,
When I use gcc to build an executable like this
gcc a.c
How I can get the linker used by LD for that executable?
Is there any option for this purpose? My LD version is 2.17.50
Best Regards
PRC
May 11,2009
Mike Frysinger
2009-05-11 05:45:37 UTC
Permalink
Post by Pan ruochen
When I use gcc to build an executable like this
gcc a.c
How I can get the linker used by LD for that executable?
Is there any option for this purpose? My LD version is 2.17.50
gcc doesnt know anything about linker scripts. that is the job of the linker.
you can see all the relevant files by linking with -Wl,--verbose.
-mike
Pan ruochen
2009-05-11 09:53:38 UTC
Permalink
In fact, I want to append the following scripts

SECTIONS {
.array : {
array = ABSOLUTE(.);
res.o (.data)
array_size = ABSOLUTE(.) - array;
}
}
to the default linker script used by ld.
Is there any simple way to do this, except copying and modifying the
default linker script?
gcc doesnt know anything about linker scripts.  that is the job of the linker.
you can see all the relevant files by linking with -Wl,--verbose.
-mike
Alan Modra
2009-05-11 10:06:41 UTC
Permalink
Post by Pan ruochen
In fact, I want to append the following scripts
[snip]

See the linker info about INSERT.
--
Alan Modra
Australia Development Lab, IBM
Ian Lance Taylor
2009-05-11 19:59:56 UTC
Permalink
Post by Pan ruochen
In fact, I want to append the following scripts
SECTIONS {
.array : {
array = ABSOLUTE(.);
res.o (.data)
array_size = ABSOLUTE(.) - array;
}
}
to the default linker script used by ld.
Is there any simple way to do this, except copying and modifying the
default linker script?
It looks like all you want is a way to get the address and size of the
.array section. If you give the section a name which can be used as a
variable name in C (i.e., no '.' character) then the linker will
automatically define __start_SECNAME and __stop_SECNAME symbols which
you can use.

http://www.airs.com/blog/archives/56

Ian
Pan ruochen
2009-05-12 07:33:35 UTC
Permalink
Post by Ian Lance Taylor
It looks like all you want is a way to get the address and size of the
.array section.  If you give the section a name which can be used as a
variable name in C (i.e., no '.' character) then the linker will
automatically define __start_SECNAME and __stop_SECNAME symbols which
you can use.
http://www.airs.com/blog/archives/56
Ian
It doesn't seem that ld can handle __start_SECNAME and __stop_SECNAME
properly for pei-i386, but It is good for elf32-i386.
My test case is:
$dd if=/dev/urandom of=res.dat count=16
$/cygdrive/d/MinGW/bin/objcopy -I binary -O pei-i386 -B i386 res.dat res.o
$/cygdrive/d/MinGW/bin/objcopy --rename-section .data=ResData res.o
$/cygdrive/d/MinGW/bin/gcc -o a.exe main.o res.o

$nm a.exe | grep ResData
00402030 A ___start_ResData
00405000 A ___stop_ResData

$/cygdrive/d/MinGW/bin/objdump -h a.exe

a.exe: file format pei-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000009d4 00401000 00401000 00000400 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00000030 00402000 00402000 00000e00 2**4
CONTENTS, ALLOC, LOAD, DATA
2 ResData 00002000 00403000 00403000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .rdata 00000110 00405000 00405000 00003000 2**4
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .bss 000000c0 00406000 00406000 00000000 2**4
ALLOC
5 .idata 00000304 00407000 00407000 00003200 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .stab 00000480 00408000 00408000 00003600 2**2
CONTENTS, READONLY, DEBUGGING, EXCLUDE
7 .stabstr 00000955 00409000 00409000 00003c00 2**0
CONTENTS, READONLY, DEBUGGING, EXCLUDE

The symbol ___start_ResData is not the start address of section
ResData. What's wrong?

--------
Best Regards
PRC
May 12,2009
Alan Modra
2009-05-12 09:07:09 UTC
Permalink
Post by Pan ruochen
The symbol ___start_ResData is not the start address of section
ResData. What's wrong?
You have hit a bug in ld. Hmm, current objcopy won't even convert
res.dat to coff/pe. This should fix the objcopy problem. I'll look
into the ld bug.

* objcopy.c (set_long_section_mode): Check input_bfd is coff
before accessing coff specific fields of bfd.

Index: binutils/objcopy.c
===================================================================
RCS file: /cvs/src/src/binutils/objcopy.c,v
retrieving revision 1.131
diff -u -p -r1.131 objcopy.c
--- binutils/objcopy.c 27 Apr 2009 13:59:43 -0000 1.131
+++ binutils/objcopy.c 12 May 2009 09:04:25 -0000
@@ -2143,7 +2143,8 @@ set_long_section_mode (bfd *output_bfd,
/* This is only relevant to Coff targets. */
if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
{
- if (style == KEEP)
+ if (style == KEEP
+ && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
}
--
Alan Modra
Australia Development Lab, IBM
Dave Korn
2009-05-12 13:36:55 UTC
Permalink
Post by Alan Modra
Post by Pan ruochen
The symbol ___start_ResData is not the start address of section
ResData. What's wrong?
You have hit a bug in ld. Hmm, current objcopy won't even convert
res.dat to coff/pe. This should fix the objcopy problem. I'll look
into the ld bug.
* objcopy.c (set_long_section_mode): Check input_bfd is coff
before accessing coff specific fields of bfd.
/* This is only relevant to Coff targets. */
if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
{
- if (style == KEEP)
+ if (style == KEEP
+ && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
}
Sorry, that dumb thinko was my fault, I neglected to consider the case of
cross-format translations. Thanks for catching it, Alan.

cheers,
DaveK
Alan Modra
2009-05-14 02:20:10 UTC
Permalink
Post by Pan ruochen
The symbol ___start_ResData is not the start address of section
ResData. What's wrong?
This cures the problem with constructor symbols on pe targets. The
trouble was that pe.em (and pep.em) align output sections to a page
boundary, and the __start_<secname> symbol was added to the internal
linker script before the output section statement alignment.

While poking around in this area I noticed a few other problems.
a) The pe and pep place_orphan functions added non-dollar sections to
the beginning of the output section. That meant input sections are
reversed from their file order, which wouldn't ordinarily cause a
problem but it's not usual linker behaviour.
b) These functions improperly added their input section statements
into the output section statement child list without using the tail
pointer of the input list. This meant only one statement was added.
c) lang_insert_orphan can be called when an existing output section's
type or flags are incompatible with an orphan input section. In
this case, I think we ought to create a new output section, but I
don't do that in this patch. Instead I just ensure we don't
duplicate the symbols.

* ldlang.c (lang_insert_orphan): Add __start_<section> symbol
assignment inside output section statement. Ensure only one
set of symbols per output section.
* emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Add non-
dollar sections before dollar sections. Correct add_child
list insertion.
* emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.

Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.306
diff -u -p -r1.306 ldlang.c
--- ld/ldlang.c 16 Apr 2009 23:07:00 -0000 1.306
+++ ld/ldlang.c 13 May 2009 00:16:36 -0000
@@ -1668,8 +1668,16 @@ lang_insert_orphan (asection *s,
push_stat_ptr (&add);
}

+ if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ address = exp_intop (0);
+
+ os_tail = ((lang_output_section_statement_type **)
+ lang_output_section_statement.tail);
+ os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
+ NULL, constraint);
+
ps = NULL;
- if (config.build_constructors)
+ if (config.build_constructors && *os_tail == os)
{
/* If the name of the section is representable in C, then create
symbols to mark the start and the end of the section. */
@@ -1688,26 +1696,19 @@ lang_insert_orphan (asection *s,
exp_intop ((bfd_vma) 1 << s->alignment_power));
lang_add_assignment (exp_assop ('=', ".", e_align));
lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
+ exp_unop (ABSOLUTE,
+ exp_nameop (NAME, ".")),
FALSE));
}
}

- if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
- address = exp_intop (0);
-
- os_tail = ((lang_output_section_statement_type **)
- lang_output_section_statement.tail);
- os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
- NULL, constraint);
-
if (add_child == NULL)
add_child = &os->children;
lang_add_section (add_child, s, os);

lang_leave_output_section_statement (0, "*default*", NULL, NULL);

- if (config.build_constructors && *ps == '\0')
+ if (ps != NULL && *ps == '\0')
{
char *symname;

Index: ld/emultempl/pe.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pe.em,v
retrieving revision 1.148
diff -u -p -r1.148 pe.em
--- ld/emultempl/pe.em 2 Apr 2009 14:42:41 -0000 1.148
+++ ld/emultempl/pe.em 12 May 2009 23:19:34 -0000
@@ -1771,6 +1771,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
char *dollar = NULL;
lang_output_section_statement_type *os;
lang_statement_list_type add_child;
+ lang_statement_union_type **pl;

/* Look through the script to see where to place this section. */
if (!link_info.relocatable
@@ -1876,47 +1877,29 @@ gld_${EMULATION_NAME}_place_orphan (asec
&add_child);
}

- {
- lang_statement_union_type **pl = &os->children.head;
-
- if (dollar != NULL)
- {
- bfd_boolean found_dollar;
-
- /* The section name has a '\$'. Sort it with the other '\$'
- sections. */
- found_dollar = FALSE;
- for ( ; *pl != NULL; pl = &(*pl)->header.next)
- {
- lang_input_section_type *ls;
- const char *lname;
+ /* If the section name has a '\$', sort it with the other '\$'
+ sections. */
+ for (pl = &os->children.head; *pl != NULL; pl = &(*pl)->header.next)
+ {
+ lang_input_section_type *ls;
+ const char *lname;

- if ((*pl)->header.type != lang_input_section_enum)
- continue;
+ if ((*pl)->header.type != lang_input_section_enum)
+ continue;

- ls = &(*pl)->input_section;
+ ls = &(*pl)->input_section;

- lname = bfd_get_section_name (ls->section->owner, ls->section);
- if (strchr (lname, '\$') == NULL)
- {
- if (found_dollar)
- break;
- }
- else
- {
- found_dollar = TRUE;
- if (strcmp (orig_secname, lname) < 0)
- break;
- }
- }
- }
+ lname = bfd_get_section_name (ls->section->owner, ls->section);
+ if (strchr (lname, '\$') != NULL
+ && (dollar == NULL || strcmp (orig_secname, lname) < 0))
+ break;
+ }

- if (add_child.head != NULL)
- {
- add_child.head->header.next = *pl;
- *pl = add_child.head;
- }
- }
+ if (add_child.head != NULL)
+ {
+ *add_child.tail = *pl;
+ *pl = add_child.head;
+ }

return os;
}
Index: ld/emultempl/pep.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/pep.em,v
retrieving revision 1.25
diff -u -p -r1.25 pep.em
--- ld/emultempl/pep.em 2 Apr 2009 14:42:41 -0000 1.25
+++ ld/emultempl/pep.em 12 May 2009 23:19:35 -0000
@@ -1546,6 +1546,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
char *dollar = NULL;
lang_output_section_statement_type *os;
lang_statement_list_type add_child;
+ lang_statement_union_type **pl;

/* Look through the script to see where to place this section. */
if (!link_info.relocatable
@@ -1651,47 +1652,29 @@ gld_${EMULATION_NAME}_place_orphan (asec
&add_child);
}

- {
- lang_statement_union_type **pl = &os->children.head;
-
- if (dollar != NULL)
- {
- bfd_boolean found_dollar;
-
- /* The section name has a '\$'. Sort it with the other '\$'
- sections. */
- found_dollar = FALSE;
- for ( ; *pl != NULL; pl = &(*pl)->header.next)
- {
- lang_input_section_type *ls;
- const char *lname;
+ /* If the section name has a '\$', sort it with the other '\$'
+ sections. */
+ for (pl = &os->children.head; *pl != NULL; pl = &(*pl)->header.next)
+ {
+ lang_input_section_type *ls;
+ const char *lname;

- if ((*pl)->header.type != lang_input_section_enum)
- continue;
+ if ((*pl)->header.type != lang_input_section_enum)
+ continue;

- ls = &(*pl)->input_section;
+ ls = &(*pl)->input_section;

- lname = bfd_get_section_name (ls->section->owner, ls->section);
- if (strchr (lname, '\$') == NULL)
- {
- if (found_dollar)
- break;
- }
- else
- {
- found_dollar = TRUE;
- if (strcmp (orig_secname, lname) < 0)
- break;
- }
- }
- }
+ lname = bfd_get_section_name (ls->section->owner, ls->section);
+ if (strchr (lname, '\$') != NULL
+ && (dollar == NULL || strcmp (orig_secname, lname) < 0))
+ break;
+ }

- if (add_child.head != NULL)
- {
- add_child.head->header.next = *pl;
- *pl = add_child.head;
- }
- }
+ if (add_child.head != NULL)
+ {
+ *add_child.tail = *pl;
+ *pl = add_child.head;
+ }

return os;
}
--
Alan Modra
Australia Development Lab, IBM
Loading...