Skip to content

Commit

Permalink
dwarf_loader: Add a lock around dwarf_decl_file() and dwarf_decl_line…
Browse files Browse the repository at this point in the history
…() calls

As this ends up racing on a tsearch() call, probably for some libdw
cache that gets updated/lookedup in concurrent pahole threads (-j N).

This cures the following, a patch for libdw will be cooked up and sent.

  (gdb) run -j -I -F dwarf vmlinux > /dev/null
  Starting program: /var/home/acme/git/pahole/build/pahole -j -I -F dwarf vmlinux > /dev/null
  warning: Expected absolute pathname for libpthread in the inferior, but got .gnu_debugdata for /lib64/libpthread.so.0.
  warning: File "/usr/lib64/libthread_db-1.0.so" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
  warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
  [New LWP 844789]
  [New LWP 844790]
  [New LWP 844791]
  [New LWP 844792]
  [New LWP 844793]
  [New LWP 844794]
  [New LWP 844795]
  [New LWP 844796]
  [New LWP 844797]
  [New LWP 844798]
  [New LWP 844799]
  [New LWP 844800]
  [New LWP 844801]
  [New LWP 844802]
  [New LWP 844803]
  [New LWP 844804]
  [New LWP 844805]
  [New LWP 844806]
  [New LWP 844807]
  [New LWP 844808]
  [New LWP 844809]
  [New LWP 844810]
  [New LWP 844811]
  [New LWP 844812]
  [New LWP 844813]
  [New LWP 844814]

  Thread 2 "pahole" received signal SIGSEGV, Segmentation fault.
  [Switching to LWP 844789]
  0x00007ffff7dfa321 in ?? () from /lib64/libc.so.6
  (gdb) bt
  #0  0x00007ffff7dfa321 in ?? () from /lib64/libc.so.6
  #1  0x00007ffff7dfa4bb in ?? () from /lib64/libc.so.6
  #2  0x00007ffff7f5eaa6 in __libdw_getsrclines (dbg=0x4a7f90, debug_line_offset=10383710, comp_dir=0x7ffff3c29f01 "/var/home/acme/git/build/v5.13.0-rc6+", address_size=address_size@entry=8, linesp=linesp@entry=0x7fffcfe04ba0, filesp=filesp@entry=0x7fffcfe04ba8)
      at dwarf_getsrclines.c:1129
  #3  0x00007ffff7f5ed14 in dwarf_getsrclines (cudie=cudie@entry=0x7fffd210caf0, lines=lines@entry=0x7fffd210cac0, nlines=nlines@entry=0x7fffd210cac8) at dwarf_getsrclines.c:1213
  #4  0x00007ffff7f64883 in dwarf_decl_file (die=<optimized out>) at dwarf_decl_file.c:66
  #5  0x0000000000425f24 in tag__init (tag=0x7fff0421b710, cu=0x7fffcc001e40, die=0x7fffd210cd30) at /var/home/acme/git/pahole/dwarf_loader.c:476
  #6  0x00000000004262ec in namespace__init (namespace=0x7fff0421b710, die=0x7fffd210cd30, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:576
  #7  0x00000000004263ac in type__init (type=0x7fff0421b710, die=0x7fffd210cd30, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:595
  #8  0x00000000004264d1 in type__new (die=0x7fffd210cd30, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:614
  #9  0x0000000000427ba6 in die__create_new_typedef (die=0x7fffd210cd30, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:1212
  #10 0x0000000000428df5 in __die__process_tag (die=0x7fffd210cd30, cu=0x7fffcc001e40, top_level=1, fn=0x45cee0 <__FUNCTION__.10> "die__process_unit", conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:1823
  #11 0x0000000000428ea1 in die__process_unit (die=0x7fffd210cd30, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:1848
  #12 0x0000000000429e45 in die__process (die=0x7fffd210ce20, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:2311
  #13 0x0000000000429ecb in die__process_and_recode (die=0x7fffd210ce20, cu=0x7fffcc001e40, conf=0x475600 <conf_load>) at /var/home/acme/git/pahole/dwarf_loader.c:2326
  #14 0x000000000042a9d6 in dwarf_cus__create_and_process_cu (dcus=0x7fffffffddc0, cu_die=0x7fffd210ce20, pointer_size=8 '\b') at /var/home/acme/git/pahole/dwarf_loader.c:2644
  #15 0x000000000042ab28 in dwarf_cus__process_cu_thread (arg=0x7fffffffddc0) at /var/home/acme/git/pahole/dwarf_loader.c:2687
  #16 0x00007ffff7ed6299 in start_thread () from /lib64/libpthread.so.0
  #17 0x00007ffff7dfe353 in ?? () from /lib64/libc.so.6
  (gdb)
  (gdb) fr 2
  1085
  (gdb) list files_lines_compare
  1086    static int
  1087    files_lines_compare (const void *p1, const void *p2)
  1088    {
  1089	  const struct files_lines_s *t1 = p1;
  1090	  const struct files_lines_s *t2 = p2;
  1091
  1092	  if (t1->debug_line_offset < t2->debug_line_offset)
  (gdb)
  1093        return -1;
  1094	  if (t1->debug_line_offset > t2->debug_line_offset)
  1095        return 1;
  1096
  1097	  return 0;
  1098    }
  1099
  1100    int
  1101    internal_function
  1102    __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
  (gdb) list __libdw_getsrclines
  1100    int
  1101    internal_function
  1102    __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
  1103                         const char *comp_dir, unsigned address_size,
  1104                         Dwarf_Lines **linesp, Dwarf_Files **filesp)
  1105    {
  1106	  struct files_lines_s fake = { .debug_line_offset = debug_line_offset };
  1107	  struct files_lines_s **found = tfind (&fake, &dbg->files_lines,
  1108                                            files_lines_compare);
  1109	  if (found == NULL)
  (gdb)
  1110        {
  1111          Elf_Data *data = __libdw_checked_get_data (dbg, IDX_debug_line);
  1112          if (data == NULL
  1113              || __libdw_offset_in_section (dbg, IDX_debug_line,
  1114                                            debug_line_offset, 1) != 0)
  1115            return -1;
  1116
  1117          const unsigned char *linep = data->d_buf + debug_line_offset;
  1118          const unsigned char *lineendp = data->d_buf + data->d_size;
  1119
  (gdb)
  1120          struct files_lines_s *node = libdw_alloc (dbg, struct files_lines_s,
  1121                                                    sizeof *node, 1);
  1122
  1123          if (read_srclines (dbg, linep, lineendp, comp_dir, address_size,
  1124                             &node->lines, &node->files) != 0)
  1125            return -1;
  1126
  1127          node->debug_line_offset = debug_line_offset;
  1128
  1129          found = tsearch (node, &dbg->files_lines, files_lines_compare);
  (gdb)

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
acmel committed Aug 12, 2021
1 parent dd13708 commit 1caed1c
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions dwarf_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define DW_OP_addrx 0xa1
#endif

static pthread_mutex_t libdw__lock = PTHREAD_MUTEX_INITIALIZER;

static uint32_t hashtags__bits = 15;
static uint32_t max_hashtags__bits = 21;

Expand Down Expand Up @@ -472,6 +474,8 @@ static void tag__init(struct tag *tag, struct cu *cu, Dwarf_Die *die)
tag->recursivity_level = 0;

if (cu->extra_dbg_info) {
pthread_mutex_lock(&libdw__lock);

int32_t decl_line;
const char *decl_file = dwarf_decl_file(die);
static const char *last_decl_file, *last_decl_file_ptr;
Expand All @@ -484,6 +488,8 @@ static void tag__init(struct tag *tag, struct cu *cu, Dwarf_Die *die)
dtag->decl_file = last_decl_file;
dwarf_decl_line(die, &decl_line);
dtag->decl_line = decl_line;

pthread_mutex_unlock(&libdw__lock);
}

INIT_LIST_HEAD(&tag->node);
Expand Down

0 comments on commit 1caed1c

Please sign in to comment.