Define __start/__stop symbols when there is only a dynamic def

Michael Matz
Mon Jan 29 15:39:00 GMT 2018


On Mon, 29 Jan 2018, H.J. Lu wrote:

> Yes, it looks very odd.  I thought the issue was with the  __start/__stop
> symbols in the shared object, not with executable.  Why is -E needed?
> I don't want to second guess.  Michael, can you provide a testcase to
> show your use case?

It's exactly as I described in the thread linked by Alan.  But sure, 
here's some code:

% cat lib.c
extern int __start___verbose[];
extern int __stop___verbose[];
extern int foo2(void);
int foo (void)
  static int my_var __attribute__((section("__verbose"))) = 5;
  if (__start___verbose == __stop___verbose  // ref_regular
      || __start___verbose[0] != 5)
    return -1;
    return 0;
% cat app.c
#include <stdlib.h>
#include <stdio.h>
extern int foo (void);
extern int __start___verbose[];
extern int __stop___verbose[];
int bar (void)
  static int my_var __attribute__((section("__verbose"))) = 6;
  // no ref_regular!
  return 0;

int main()
  if (bar () != 0)
      printf("main: wrong __start___verbose\n");
  return 0;
% cc -g   -c -o app.o app.c
% cc -g -fPIC   -c -o lib.o lib.c
% cc -B./ -shared -o lib.o -Wl,-R,.
% cc -B./ -o app app.o -ldl -Wl,-R,.

(This assumes that ./ld is the new binutils link editor)

% readelf -sW | grep verbose
     7: 0000000000201024     0 NOTYPE  GLOBAL PROTECTED   23 __stop___verbose
    11: 0000000000201020     0 NOTYPE  GLOBAL PROTECTED   23 __start___verbose
    56: 0000000000201024     0 NOTYPE  GLOBAL PROTECTED   23 __stop___verbose
    63: 0000000000201020     0 NOTYPE  GLOBAL PROTECTED   23 __start___verbose

So, provides the symbols we want.

% readelf -sW app | grep verbose

But app itself does not.  As Alan and me discussed in the thread this is 
unfortunate and not how binutils worked before 2.29, but OTOH it's how it 
was documented all along.  But still on the other other hand (ahem) 
pacemaker relies on the above (i.e. expects that app does provide these 
symbols in the above situation).  One work-around would have been to use -u 
__start___verbose, except that work-around doesn't work with unpatched 
binutils, because the -u symbols aren't ref_regular:

% cc -Wl,-u,__start___verbose -B./ -o app app.o -ldl -Wl,-R,.
./ld: warning: type and size of dynamic symbol `__start___verbose' are not 

I proposed two alternatives to make the -u work-around work.  Alan 
thankfully seems to have reconsidered and instead changed elflink such 
that now app provides the symbols even without changes to the link command 
line, i.e. like binutils behaved before 2.29.

Or, rather, there's one more thing missing to make it really behave like < 
2.29, and that's the reason why Alans testcase needs -E currently.  When 
we create a start/stop symbol it needs to be dynamic (otherwise it doesn't 
make much sense), but isn't automatically made so, so this is needed in 
addition, then the -E is useless:

@@ -14347,6 +14356,7 @@ bfd_elf_define_start_stop (struct bfd_link_info 
       h->def_dynamic = 0;
       h->start_stop = 1;
       h->u2.start_stop_section = sec;
+      bfd_elf_link_record_dynamic_symbol (info, h);
       if (symbol[0] == '.')
          /* .startof. and .sizeof. symbols are local.  */

Or something along the lines (perhaps doing this only in the 
C-representable case, and then only if not made hidden or so).


More information about the Binutils mailing list