Subject: Re: Section attributes from ld
From: [email-masked] (Jon Thackray)

16 Jul 1997 14:38:14 -0700
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
References: <[email-masked]>
	<[email-masked]>
	<[email-masked]>
	<[email-masked]>
Original-To: [email-masked], [email-masked]
In-Reply-To: <[email-masked]>
Original-Sender: [email-masked]

Jon Thackray writes:
 > Jon Thackray writes:
 >  > [email-masked] writes:
 >  >  > >How does ld determine which attributes sections are to have? By
 >  >  > >attributes, I mean things like:-
 >  >  > 
 >  >  > >Contains code, contains initialised data, should be laoded with
 >  >  > >execute permission, should be loaded with read permission, should be
 >  >  > >loaded with write permission etc.
 >  >  > 
 >  >  > The attributes are based on the attributes of the input sections which
 >  >  > are mapped into the output sections.  Take a look at
 >  >  > gas/config/obj-coff.c to see how to use the .section directive in an
 >  >  > assembler file.
 >  > 
 >  > As far as I can see, this allows me no control over the flags I'm
 >  > talking about. The ones I mean are documented in MSDN as:-
 >  > 
 >  > IMAGE_SCN_MEM_DISCARDABLE	0x02000000
 >  > IMAGE_SCN_MEM_NOT_CACHED	0x04000000
 >  > IMAGE_SCN_MEM_NOT_PAGED		0x08000000
 >  > IMAGE_SCN_MEM_SHARED		0x10000000
 >  > IMAGE_SCN_MEM_EXECUTE		0x20000000
 >  > IMAGE_SCN_MEM_READ		0x40000000
 >  > IMAGE_SCN_MEM_WRITE		0x80000000
 >  > 
 >  > It would appear that as automatcially puts MEM_READ and MEM_EXECUTE on
 >  > the .text section, MEM_READ and MEM_WRITE on the .data section and the
 >  > same on the .bss section. For sections it doesn't know about (eg I
 >  > have one called .dyfix), it outs none of these. However, my compiler,
 >  > when generating these sections, does add attributes such as MEM_READ
 >  > and MEM_WRITE, but then ld appears to throw them away (at least binary
 >  > editing the resulting executable or looking at it with any of the
 >  > tools available shows them to have gone away).
 > 
 > As an experiment, I made an object file without the MEM_EXECUTE flag
 > for the .text section, and then linked it (with nothing else at all).
 > ld put the MEM_EXECUTE flag back on the .text section, which suggests
 > that the attributes aren't entirely based on those incoming.

Further investigation suggests there is a bug in bfd/peicode.h In
there we find a comment, followed by some code. The code and the
comment disagree about the use of IMAGE_SCN_MEM_READ. The comment
suggests it should be set for all sections under NT. The code only
sets it for a collection of recognised sections. It seems this can be
fixed either by changing the first line to say:-

    int flags = scnhdr_int->s_flags | IMAGE_SCN_MEM_READ;

or by adding a final else clause, eg

    else {
      flags |= IMAGE_SCN_MEM_READ;
    }

  /* Extra flags must be set when dealing with NT.  All sections should also
     have the IMAGE_SCN_MEM_READ (0x40000000) flag set.  In addition, the
     .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data
     sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
     (this is especially important when dealing with the .idata section since
     the addresses for routines from .dlls must be overwritten).  If .reloc
     section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
     (0x02000000).  Also, the resource data should also be read and
     writable.  */

  /* FIXME: alignment is also encoded in this field, at least on ppc (krk) */
  /* FIXME: even worse, I don't see how to get the original alignment field*/
  /*        back...                                                        */

  {
    int flags = scnhdr_int->s_flags;
    if (strcmp (scnhdr_int->s_name, ".data")  == 0 ||
	strcmp (scnhdr_int->s_name, ".CRT")   == 0 ||
	strcmp (scnhdr_int->s_name, ".rsrc")  == 0 ||
	strcmp (scnhdr_int->s_name, ".bss")   == 0)
      flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
    else if (strcmp (scnhdr_int->s_name, ".text") == 0)
      flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
    else if (strcmp (scnhdr_int->s_name, ".reloc") == 0)
      flags = SEC_DATA| IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
    else if (strcmp (scnhdr_int->s_name, ".idata") == 0)
      flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | SEC_DATA;     
    else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
	     || strcmp (scnhdr_int->s_name, ".edata") == 0)
      flags =  IMAGE_SCN_MEM_READ | SEC_DATA;     
    else if (strcmp (scnhdr_int->s_name, ".pdata") == 0)
      flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES |
			  IMAGE_SCN_MEM_READ ;
    /* Remember this field is a max of 8 chars, so the null is _not_ there
       for an 8 character name like ".reldata". (yep. Stupid bug) */
    else if (strncmp (scnhdr_int->s_name, ".reldata", strlen(".reldata")) == 0)
      flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
	       IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
    else if (strcmp (scnhdr_int->s_name, ".ydata") == 0)
      flags =  IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
	       IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
    else if (strncmp (scnhdr_int->s_name, ".drectve", strlen(".drectve")) == 0)
      flags =  IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
#ifdef POWERPC_LE_PE
    else if (strncmp (scnhdr_int->s_name, ".stabstr", strlen(".stabstr")) == 0)
      {
	flags =  IMAGE_SCN_LNK_INFO;
      }
    else if (strcmp (scnhdr_int->s_name, ".stab") == 0)
      {
	flags =  IMAGE_SCN_LNK_INFO;
      }
#endif

    bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
  }
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".