mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	addr2line.c: support debuglink by build_id
Currently, addr2line.c supports only one path format of debuglink: "/usr/lib/debug/usr/bin/ruby.debug". However, recent debian packages seem to use another format by build_id: "/usr/lib/debug/.build-id/ab/cdef1234.debug".5d1bb29841/dh_strip (L292)5d1bb29841/dh_strip (L353)This changeset makes ruby backtrace support the second format.
This commit is contained in:
		
							parent
							
								
									8c5ec10038
								
							
						
					
					
						commit
						c718c30007
					
				
				
				Notes:
				
					git
				
				2020-12-11 14:09:00 +09:00 
				
			
			
			
		
		
					 1 changed files with 59 additions and 3 deletions
				
			
		
							
								
								
									
										62
									
								
								addr2line.c
									
										
									
									
									
								
							
							
						
						
									
										62
									
								
								addr2line.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -526,13 +526,25 @@ append_obj(obj_info_t **objp)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ELF
 | 
			
		||||
/* Ideally we should check 4 paths to follow gnu_debuglink:
 | 
			
		||||
 *
 | 
			
		||||
 *   - /usr/lib/debug/.build-id/ab/cdef1234.debug
 | 
			
		||||
 *   - /usr/bin/ruby.debug
 | 
			
		||||
 *   - /usr/bin/.debug/ruby.debug
 | 
			
		||||
 *   - /usr/lib/debug/usr/bin/ruby.debug.
 | 
			
		||||
 *
 | 
			
		||||
 * but we handle only two cases for now as the two formats are
 | 
			
		||||
 * used by some linux distributions.
 | 
			
		||||
 *
 | 
			
		||||
 * See GDB's info for detail.
 | 
			
		||||
 * https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
 | 
			
		||||
static void
 | 
			
		||||
follow_debuglink(const char *debuglink, int num_traces, void **traces,
 | 
			
		||||
		 obj_info_t **objp, line_info_t *lines, int offset)
 | 
			
		||||
{
 | 
			
		||||
    /* Ideally we should check 4 paths to follow gnu_debuglink,
 | 
			
		||||
       but we handle only one case for now as this format is used
 | 
			
		||||
       by some linux distributions. See GDB's info for detail. */
 | 
			
		||||
    static const char global_debug_dir[] = "/usr/lib/debug";
 | 
			
		||||
    const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
 | 
			
		||||
    char *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -559,6 +571,37 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
 | 
			
		|||
    o2->path = o1->path;
 | 
			
		||||
    fill_lines(num_traces, traces, 0, objp, lines, offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug"
 | 
			
		||||
static void
 | 
			
		||||
follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_traces, void **traces,
 | 
			
		||||
                          obj_info_t **objp, line_info_t *lines, int offset)
 | 
			
		||||
{
 | 
			
		||||
    static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
 | 
			
		||||
    const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
 | 
			
		||||
    char *p;
 | 
			
		||||
    obj_info_t *o1 = *objp, *o2;
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return;
 | 
			
		||||
 | 
			
		||||
    memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
 | 
			
		||||
    p = binary_filename + global_debug_dir_len;
 | 
			
		||||
    for (i = 0; i < build_id_size; i++) {
 | 
			
		||||
        static const char tbl[] = "0123456789abcdef";
 | 
			
		||||
        unsigned char n = build_id[i];
 | 
			
		||||
        *p++ = tbl[n / 16];
 | 
			
		||||
        *p++ = tbl[n % 16];
 | 
			
		||||
        if (i == 0) *p++ = '/';
 | 
			
		||||
    }
 | 
			
		||||
    strcpy(p, ".debug");
 | 
			
		||||
 | 
			
		||||
    append_obj(objp);
 | 
			
		||||
    o2 = *objp;
 | 
			
		||||
    o2->base_addr = o1->base_addr;
 | 
			
		||||
    o2->path = o1->path;
 | 
			
		||||
    fill_lines(num_traces, traces, 0, objp, lines, offset);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
| 
						 | 
				
			
			@ -1616,6 +1659,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
 | 
			
		|||
    ElfW(Ehdr) *ehdr;
 | 
			
		||||
    ElfW(Shdr) *shdr, *shstr_shdr;
 | 
			
		||||
    ElfW(Shdr) *gnu_debuglink_shdr = NULL;
 | 
			
		||||
    ElfW(Shdr) *note_gnu_build_id = NULL;
 | 
			
		||||
    int fd;
 | 
			
		||||
    off_t filesize;
 | 
			
		||||
    char *file;
 | 
			
		||||
| 
						 | 
				
			
			@ -1688,6 +1732,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
 | 
			
		|||
	    /* if (!strcmp(section_name, ".dynsym")) */
 | 
			
		||||
	    dynsym_shdr = shdr + i;
 | 
			
		||||
	    break;
 | 
			
		||||
          case SHT_NOTE:
 | 
			
		||||
            if (!strcmp(section_name, ".note.gnu.build-id")) {
 | 
			
		||||
                note_gnu_build_id = shdr + i;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
	  case SHT_PROGBITS:
 | 
			
		||||
	    if (!strcmp(section_name, ".gnu_debuglink")) {
 | 
			
		||||
		gnu_debuglink_shdr = shdr + i;
 | 
			
		||||
| 
						 | 
				
			
			@ -1803,6 +1852,13 @@ use_symtab:
 | 
			
		|||
			     num_traces, traces,
 | 
			
		||||
			     objp, lines, offset);
 | 
			
		||||
	}
 | 
			
		||||
        if (note_gnu_build_id && check_debuglink) {
 | 
			
		||||
            ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
 | 
			
		||||
            const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
 | 
			
		||||
            follow_debuglink_build_id(build_id, nhdr->n_descsz,
 | 
			
		||||
			       num_traces, traces,
 | 
			
		||||
			       objp, lines, offset);
 | 
			
		||||
        }
 | 
			
		||||
	goto finish;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue