bfd_link_order vs. asection

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

bfd_link_order vs. asection

Alan Modra
Some time ago, I looked at moving the "offset" and "size" fields of
struct bfd_link_order out of the common part and into the "data" and
"reloc" union fields.  The idea was to free up space in "indirect",
so that I could stash some pointers there for use by the linker.  I
never finished the linker patch, so won't commit the change to
bfd_link_order.  This part just changes some places that can use fields
duplicated in the section struct.

        * coff-h8300.c (h8300_reloc16_extra_cases): Use input section
        "output_offset" instead of link order "offset".
        * coff-h8500.c (extra_case): Likewise.
        * coff-w65.c (w65_reloc16_extra_cases): Likewise.
        * coff-z80.c (extra_case): Likewise.
        * coff-z8k.c (extra_case): Likewise.
        * linker.c (default_indirect_link_order): Likewise, "size" too.
        * ecoff.c (ecoff_indirect_link_order): Likewise.

Index: bfd/coff-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-h8300.c,v
retrieving revision 1.36
diff -u -p -r1.36 coff-h8300.c
--- bfd/coff-h8300.c 4 May 2005 15:53:02 -0000 1.36
+++ bfd/coff-h8300.c 24 Dec 2005 12:27:51 -0000
@@ -671,7 +671,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       /* Get the address of the target of this branch.  */
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma);
 
@@ -703,7 +703,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
       /* Get the address of the instruction (not the reloc).  */
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma + 1);
 
@@ -817,7 +817,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
       /* Get the address of the next instruction.  */
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma + 1);
 
@@ -864,7 +864,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
       /* Get the address of the instruction (not the reloc).  */
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma - 1);
 
@@ -925,7 +925,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
       /* Get the address of the instruction (not the reloc).  */
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma + 2);
 
@@ -1064,7 +1064,7 @@ h8300_reloc16_extra_cases (bfd *abfd, st
       /* Get the address of the target of this branch.  */
       value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
 
-      dot = (link_order->offset
+      dot = (input_section->output_offset
      + dst_address
      + link_order->u.indirect.section->output_section->vma) + 1;
 
Index: bfd/coff-h8500.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-h8500.c,v
retrieving revision 1.14
diff -u -p -r1.14 coff-h8500.c
--- bfd/coff-h8500.c 4 May 2005 15:53:02 -0000 1.14
+++ bfd/coff-h8500.c 24 Dec 2005 12:27:52 -0000
@@ -245,9 +245,9 @@ extra_case (in_abfd, link_info, link_ord
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = link_order->offset
-  + *dst_ptr
-    + link_order->u.indirect.section->output_section->vma;
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
+       + input_section->output_section->vma);
  int gap = dst - dot - 1; /* -1 since were in the odd byte of the
     word and the pc's been incremented.  */
 
@@ -269,9 +269,9 @@ extra_case (in_abfd, link_info, link_ord
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = link_order->offset
-  + *dst_ptr
-    + link_order->u.indirect.section->output_section->vma;
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
+       + input_section->output_section->vma);
  int gap = dst - dot - 1; /* -1 since were in the odd byte of the
     word and the pc's been incremented.  */
 
Index: bfd/coff-w65.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-w65.c,v
retrieving revision 1.15
diff -u -p -r1.15 coff-w65.c
--- bfd/coff-w65.c 4 May 2005 15:53:04 -0000 1.15
+++ bfd/coff-w65.c 24 Dec 2005 12:27:52 -0000
@@ -316,9 +316,9 @@ w65_reloc16_extra_cases (abfd, link_info
       {
  int gap = bfd_coff_reloc16_get_value (reloc, link_info,
       input_section);
- bfd_vma dot = link_order->offset
-  + dst_address
-    + link_order->u.indirect.section->output_section->vma;
+ bfd_vma dot = (dst_address
+       + input_section->output_offset
+       + input_section->output_section->vma);
 
  gap -= dot + 1;
  if (gap < -128 || gap > 127)
@@ -340,9 +340,9 @@ w65_reloc16_extra_cases (abfd, link_info
       {
  bfd_vma gap = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = link_order->offset
-  + dst_address
-    + link_order->u.indirect.section->output_section->vma;
+ bfd_vma dot = (dst_address
+       + input_section->output_offset
+       + input_section->output_section->vma);
 
  /* This wraps within the page, so ignore the relativeness, look at the
    high part.  */
Index: bfd/coff-z80.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-z80.c,v
retrieving revision 1.1
diff -u -p -r1.1 coff-z80.c
--- bfd/coff-z80.c 25 Oct 2005 17:40:09 -0000 1.1
+++ bfd/coff-z80.c 24 Dec 2005 12:27:52 -0000
@@ -200,8 +200,8 @@ extra_case (bfd *in_abfd,
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = (link_order->offset
-       + *dst_ptr
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
        + input_section->output_section->vma);
  int gap = dst - dot - 1;  /* -1, Since the offset is relative
      to the value of PC after reading
Index: bfd/coff-z8k.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-z8k.c,v
retrieving revision 1.20
diff -u -p -r1.20 coff-z8k.c
--- bfd/coff-z8k.c 26 Aug 2005 09:47:43 -0000 1.20
+++ bfd/coff-z8k.c 24 Dec 2005 12:27:52 -0000
@@ -230,8 +230,8 @@ extra_case (bfd *in_abfd,
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = (link_order->offset
-       + *dst_ptr
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
        + input_section->output_section->vma);
  int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
                                      word and the pc's been incremented.  */
@@ -258,8 +258,8 @@ extra_case (bfd *in_abfd,
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = (link_order->offset
-       + *dst_ptr
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
        + input_section->output_section->vma);
  int gap = dst - dot - 1;  /* -1, since we're in the odd byte of the
                                      word and the pc's been incremented.  */
@@ -289,8 +289,8 @@ extra_case (bfd *in_abfd,
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = (link_order->offset
-       + *dst_ptr
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
        + input_section->output_section->vma);
  int gap = dst - dot - 2;
 
@@ -318,8 +318,8 @@ extra_case (bfd *in_abfd,
       {
  bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
   input_section);
- bfd_vma dot = (link_order->offset
-       + *dst_ptr
+ bfd_vma dot = (*dst_ptr
+       + input_section->output_offset
        + input_section->output_section->vma);
  int gap = dst - dot - 2;
 
Index: bfd/ecoff.c
===================================================================
RCS file: /cvs/src/src/bfd/ecoff.c,v
retrieving revision 1.48
diff -u -p -r1.48 ecoff.c
--- bfd/ecoff.c 6 Jul 2005 10:35:41 -0000 1.48
+++ bfd/ecoff.c 24 Dec 2005 12:27:56 -0000
@@ -4002,11 +4002,10 @@ ecoff_indirect_link_order (bfd *output_b
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
-  if (link_order->size == 0)
-    return TRUE;
-
   input_section = link_order->u.indirect.section;
   input_bfd = input_section->owner;
+  if (input_section->size == 0)
+    return TRUE;
 
   BFD_ASSERT (input_section->output_section == output_section);
   BFD_ASSERT (input_section->output_offset == link_order->offset);
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.51
diff -u -p -r1.51 linker.c
--- bfd/linker.c 24 Oct 2005 11:24:31 -0000 1.51
+++ bfd/linker.c 24 Dec 2005 12:28:21 -0000
@@ -2717,11 +2717,10 @@ default_indirect_link_order (bfd *output
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
-  if (link_order->size == 0)
-    return TRUE;
-
   input_section = link_order->u.indirect.section;
   input_bfd = input_section->owner;
+  if (input_section->size == 0)
+    return TRUE;
 
   BFD_ASSERT (input_section->output_section == output_section);
   BFD_ASSERT (input_section->output_offset == link_order->offset);
@@ -2810,9 +2807,9 @@ default_indirect_link_order (bfd *output
     goto error_return;
 
   /* Output the section contents.  */
-  loc = link_order->offset * bfd_octets_per_byte (output_bfd);
+  loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
   if (! bfd_set_section_contents (output_bfd, output_section,
-  new_contents, loc, link_order->size))
+  new_contents, loc, input_section->size))
     goto error_return;
 
   if (contents != NULL)

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Reg initializing data in segments other than .data

Prasad B-2
Hello,

In my linker script, there is a section '.shared_section', in which
variables that need to be shared across multiple processors go. That
section becomes '.shared_segment' in the elf executable. So, the linker
script looks as follows:

...

.shared_segment 0x80800000 : {
     *(.shared_section)
}

Variables defined in '.shared_section' should be able to be initialized.
That is '.shared_segment' should have the same semantics as the 'data'
segment.

Is there any way of specifying attributes to that segment in the linker
script so that linker actually copies the corresponding values of
variables to the elf executable ? It would be preferable not to push the
'shared_section' into 'data' segment.

regards,
Prasad.


Reply | Threaded
Open this post in threaded view
|

Re: Reg initializing data in segments other than .data

H.J. Lu-27
On Thu, Jan 05, 2006 at 03:33:53PM -0700, Prasad Venkata Boddupalli wrote:

> Hello,
>
> In my linker script, there is a section '.shared_section', in which
> variables that need to be shared across multiple processors go. That
> section becomes '.shared_segment' in the elf executable. So, the linker
> script looks as follows:
>
> ...
>
> .shared_segment 0x80800000 : {
>     *(.shared_section)
> }
>
> Variables defined in '.shared_section' should be able to be initialized.
> That is '.shared_segment' should have the same semantics as the 'data'
> segment.
>
> Is there any way of specifying attributes to that segment in the linker
> script so that linker actually copies the corresponding values of
> variables to the elf executable ? It would be preferable not to push the
> 'shared_section' into 'data' segment.

You may need linker changes to do what you want. In fact, I implemented
a very similar scheme for x86, x86-64 and ia64:

    *  The changes to the psABI are

       1. To the section attribute flags, add SHF_INTC_SHARABLE

          #define SHF_INTC_SHARABLE 0x01000000

          described as follows:

          SHF_INTC_SHARABLE

          The section contains data that will be placed in sharable
memory
          accessible from more than one processor in a non-uniform
memory access
          (NUMA) multiprocessor system. Implementations need not
support
          sharable memory.

           
       2. To the special section indexes, add SHN_INTC_SHARABLE_COMMON

          #define SHN_INTC_SHARABLE_COMMON (SHN_LOOS + 10)

          described as follows:

          SHN_INTC_SHARABLE_COMMON

          Symbols defined relative to this section are common symbols,
such as
          FORTRAN COMMON or unallocated C external variables that are
to be
          placed in sharable memory. Implementations need not support
sharable
          memory.

           
       3. To the discussion of special section index value semantics,
add:

          SHN_INTC_SHARABLE_COMMON

          The symbol labels a common block in sharable memory that has
not yet
          been allocated. The linker editor treats these exactly as it
does
          symbols with section index SHN_COMMON, except that it
allocates the
          symbol at an address in sharable memory. Implementations need
not
          support sharable memory.

           
       4. To Special Sections, add the following:

          .sharable_bss, type SHT_NOBITS, attributes
          SHF_ALLOC+SHF_WRITE+SHF_INTC_SHARABLE

          .sharable_data, type SHT_PROGBITS, attributes
          SHF_ALLOC+SHF_WRITE+SHF_INTC_SHARABLE

          .sharable_bss

          This section holds uninitialized data that contribute to the
program's
          memory image. By definition, the system initializes the data
with
          zeros when the program begins to run. The section resides in
sharable
          memory. Implementations need not support sharable memory.

          .sharable_data

          This section holds initialized data that contribute to the
program's
          memory image. The section resides in sharable memory.
Implementations
          need not support sharable memory.

           
       5. To the Program Header section, add a segment type PH_INTC_SHR

          #define PT_INTC_SHR (PT_LOOS + 0x494e540)

          The array element specifies the location and size of a
sharable memory
          information area. The interpretation of the sharable memory
          information area is implementation-dependent. Implementations
need not
          support sharable memory.
           

    * A new assembly directive:

      .sharable_common SYMBOL , LENGTH, ALIGNMENT

          It will generate a SHN_SHARABLE_COMMON symbol of size LENGTH
aligned at ALIGMENT.

    * Special sections:

       1. .sharable_bss.*. It has the same section type and attribute
as .sharable_bss.
       2. .sharable_data.*. It has the same section type and attribute
as .sharable_data.
       3. .gnu.linkonce.shrb.*. It has the same section type and
attribute as .sharable_bss. If linker sees more than one section with
the same name, only one section will be kept.
       4. .gnu.linkonce.shrd.*. It has the same section type and
attribute as .sharable_data. If linker sees more than one section with
the same name, only one section will be kept.
       5. Assembler will set the proper type and attribute for special
sections listed above, regardless what the assembly directive
specifies. No other sections with the SHF_INTC_SHARABLE attribute are
allowed.
       6. For shared library and executable outputs, linker will group
together .sharable_bss, .sharable_bss.* and  .gnu.linkonce.shrb.*
sections to generate a single sharable_bss section, and group together
.sharable_data, .sharable_data.* and  .gnu.linkonce.shrd.* sections to
generate a single sharable_data section. The final .sharable_bss and
.sharable_data sections should be page-aligned and padded to an
integral number of full pages. Linker will provide 2 sets of hidden
symbols, __sharable_bss_start/__sharable_bss_end,
__sharable_data_start/__sharable_end, to mark the start and the end
addresses of .sharable_bss and .sharable_data sections. The value of
the start symbol is the starting address of the section and the value
of the end symbol is the address immediately following the section.


H.J.

Reply | Threaded
Open this post in threaded view
|

Re: Reg initializing data in segments other than .data

Nick Clifton
In reply to this post by Prasad B-2
Hi Prasad,

> In my linker script, there is a section '.shared_section', in which
> variables that need to be shared across multiple processors go. That
> section becomes '.shared_segment' in the elf executable. So, the linker
> script looks as follows:

> .shared_segment 0x80800000 : {
>     *(.shared_section)
> }

This creates a *section* in the output file called ".shared_segment".
It does not create a *segment* in the output file.

> Variables defined in '.shared_section' should be able to be initialized.
> That is '.shared_segment' should have the same semantics as the 'data'
> segment.

Be very careful of your semantics here.  Sections are different from
segments.  Assuming that we are talking about ELF format files then,
usually, *sections* exist in object files and have names (and other
attributes), whereas *segments* exits in executable files and do not
have names.  (But they do have other attributes).

It appears that what you want is to have the linker create at least two
different segments in the executable that it is creating, one for
ordinary data and one for shared data.  In both of these segments you
want the data values to be initialised at the start of run time.  There
may be other segments for executable code, non initialised data and so
on, but that is not important for the moment.  Right ?

The linker script syntax does not (currently) allow you to specify
segments or their attributes explicitly.  Instead the linker attempts to
create the minimum number of segments necessary in order to group the
sections from the input files in the way that the linker script
dictates.  (The linker sometimes fails at this task.  See the section
describing the "not enough room for program headers" error message in
the linker documentation).

So, really, all you want is to make sure that the shared data is not put
into the segment that is going to be assigned to ordinary data and that
the shared data segment created by the linker has the correct
attributes.  Getting the correct attributes should be easy.  The linker
calculates the attributes of the segments it creates based on the
attributes of the input sections assigned to those segments.  So
provided that the symbols in your .shared_section sections have the
STT_OBJECT attribute (or at least do not have the STT_COMMON attribute)
then the linker should end up assigning them to a segment with the
SHF_ALLOC attribute, which will ensure that they are initialised at
run-time.

In order to make sure that the shared data is not placed into the same
segment as the non-shared data you need to make sure that your linker
scripts places these two types of input into different output sections
which will end up at least a page apart in memory.  So starting with
your current fragment

 > .shared_segment 0x80800000 : {
 >     *(.shared_section)
 > }

All you really need to do is to make sure that the non-shared data is
placed nowhere near 0x80800000.  eg:

   .data 0x00000000 : {
       *(.data)
    }

Cheers
   Nick




Reply | Threaded
Open this post in threaded view
|

Re: Reg initializing data in segments other than .data

Prasad B-2
I earlier asked as how to have variables assigned to a segment different
from .data initialized while loading. Since I have my own loader, my
question was whether the linker, depending upon the attributes of a
section, writes those initial values into the executable.

Thanks to Mr.Lu and Mr.Nick for their detailed answers. However Mr.Lu
wrote that it might need changes to linker while Mr.Nick in the following
fragment hinted that linker already does that.

On Mon, 9 Jan 2006, Nick Clifton wrote:

> The linker script syntax does not (currently) allow you to specify segments or
> their attributes explicitly.  Instead the linker attempts to create the
> minimum number of segments necessary in order to group the sections from the
> input files in the way that the linker script dictates.  (The linker sometimes
> fails at this task.  See the section describing the "not enough room for
> program headers" error message in the linker documentation).
>
> So, really, all you want is to make sure that the shared data is not put into
> the segment that is going to be assigned to ordinary data and that the shared
> data segment created by the linker has the correct attributes.  Getting the
> correct attributes should be easy.  The linker calculates the attributes of
> the segments it creates based on the attributes of the input sections assigned
> to those segments.  So provided that the symbols in your .shared_section
> sections have the STT_OBJECT attribute (or at least do not have the STT_COMMON
> attribute) then the linker should end up assigning them to a segment with the
> SHF_ALLOC attribute, which will ensure that they are initialised at run-time.

However, when I load the file image of a segment, whose attributes are
indeed 'ALLOC' and derived from a section one of whose attributes is
'not' STT_COMMON, the values are zero and not the same as initialized
values. Which suggests that linker might not have written the correct
values into the corresponding segment portion of the executable. Am I
probably right on that conclusion ?

However, the file size of the segment equals memory size which probably
hints that the values are copied into the executable. But, why could they
be zero ?

thanks to this informative list,
Prasad.