folly: signal-handler: dynamic cache size, based on number of dynamic-loaded ELF...
authorLucian Grijincu <lucian@fb.com>
Wed, 12 Oct 2016 00:03:55 +0000 (17:03 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Wed, 12 Oct 2016 00:08:59 +0000 (17:08 -0700)
commit74ea0a31f65bcb4a6debc997a57f9cc1b3882d6b
treeb8a2554e8d662c06fc5322963cf3fb875623f844
parent70b158bb1a240cf5c50b9fd295f538f6eb2432a7
folly: signal-handler: dynamic cache size, based on number of dynamic-loaded ELF files

Summary:
I added kFatalSignalHandlerCacheSize in {D3984649}, and chose a big
number to satisfy most use-cases. But the size increase is non-trivial.

Memory usage:

- before: 5.1 MB in folly::symbolizer::SignalSafeElfCache::SignalSafeElfCache
- after: 80.0 MB in folly::symbolizer::SignalSafeElfCache::SignalSafeElfCache

Switch to a dynamic approach and everyone pays for what they use.

https://github.com/bminor/glibc/blob/ee19f1de0d0da24114be554fdf94243c0ec6b86c/elf/rtld-debugger-interface.txt#L10-L20
```
The r_debug structure contains (amongst others) the following fields:

  struct link_map *r_map:
    A linked list of loaded objects.

  enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state:
    The current state of the r_map list.  RT_CONSISTENT means that r_map
    is not currently being modified and may safely be inspected.  RT_ADD
    means that an object is being added to r_map, and that the list is
    not guaranteed to be consistent.  Likewise RT_DELETE means that an
    object is being removed from the list.
```

https://github.com/bminor/glibc/blob/ee19f1de0d0da24114be554fdf94243c0ec6b86c/elf/rtld.c#L303-L307
```
  /* Call the OS-dependent function to set up life so we can do things like
     file access.  It will call `dl_main' (below) to do all the real work
     of the dynamic linker, and then unwind our frame and run the user
     entry point on the same stack we entered on.  */
  start_addr = _dl_sysdep_start (arg, &dl_main);
```

dl_main: https://github.com/bminor/glibc/blob/ee19f1de0d0da24114be554fdf94243c0ec6b86c/elf/rtld.c#L1192-L1199
```
  /* Initialize the data structures for the search paths for shared
     objects.  */
  _dl_init_paths (library_path);

  /* Initialize _r_debug.  */
  struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr,
    LM_ID_BASE);
  r->r_state = RT_CONSISTENT;
...

  /* We start adding objects.  */
  r->r_state = RT_ADD;
  _dl_debug_state ();
  LIBC_PROBE (init_start, 2, LM_ID_BASE, r);

...

  /* Notify the debugger all new objects are now ready to go.  We must re-get
     the address since by now the variable might be in another object.  */
  r = _dl_debug_initialize (0, LM_ID_BASE);
  r->r_state = RT_CONSISTENT;
  _dl_debug_state ();
  LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);

```

Reviewed By: bixue2010

Differential Revision: D3996974

fbshipit-source-id: e24d72e3cc0339e4cf1acdd2f4c9a7ebfcfdf739
folly/experimental/symbolizer/ElfCache.cpp
folly/experimental/symbolizer/ElfCache.h
folly/experimental/symbolizer/SignalHandler.cpp
folly/experimental/symbolizer/SignalHandler.h