Project

General

Profile

Bug #17585 ยป ruby-dwarf5-debug_line.patch

xtkoba (Tee KOBAYASHI), 02/10/2021 04:38 PM

View differences:

addr2line.c
160 160
    struct dwarf_section debug_line;
161 161
    struct dwarf_section debug_ranges;
162 162
    struct dwarf_section debug_str;
163
    struct dwarf_section debug_line_str;
163 164
    struct obj_info *next;
164 165
} obj_info_t;
165 166

  
166
#define DWARF_SECTION_COUNT 5
167
#define DWARF_SECTION_COUNT 6
167 168

  
168 169
static struct dwarf_section *
169 170
obj_dwarf_section_at(obj_info_t *obj, int n)
......
173 174
        &obj->debug_info,
174 175
        &obj->debug_line,
175 176
        &obj->debug_ranges,
176
        &obj->debug_str
177
        &obj->debug_str,
178
        &obj->debug_line_str,
177 179
    };
178 180
    if (n < 0 || DWARF_SECTION_COUNT <= n) {
179 181
        abort();
......
228 230
    return r;
229 231
}
230 232

  
233
static const char *get_nth_dirname_5(unsigned long, uint16_t, uint8_t, uint8_t, obj_info_t *, char *);
231 234
static const char *
232
get_nth_dirname(unsigned long dir, char *p)
235
get_nth_dirname(unsigned long dir, uint16_t version, uint8_t format, uint8_t address_size, obj_info_t *obj, char *p)
233 236
{
237
    if (version >= 5) {
238
	return get_nth_dirname_5(dir, version, format, address_size, obj, p);
239
    }
240

  
234 241
    if (!dir--) {
235 242
	return "";
236 243
    }
......
246 253
    return p;
247 254
}
248 255

  
256
static void fill_filename_5(int, uint16_t, uint8_t, uint8_t, char *, char *, line_info_t *, obj_info_t *);
249 257
static void
250
fill_filename(int file, char *include_directories, char *filenames, line_info_t *line, obj_info_t *obj)
258
fill_filename(int file, uint16_t version, uint8_t format, uint8_t address_size, char *include_directories, char *filenames, line_info_t *line, obj_info_t *obj)
251 259
{
252 260
    int i;
253 261
    char *p = filenames;
254 262
    char *filename;
255 263
    unsigned long dir;
264

  
265
    if (version >= 5) {
266
	fill_filename_5(file, version, format, address_size, include_directories, filenames, line, obj);
267
	return;
268
    }
269

  
256 270
    for (i = 1; i <= file; i++) {
257 271
	filename = p;
258 272
	if (!*p) {
......
271 285

  
272 286
	if (i == file) {
273 287
	    line->filename = filename;
274
	    line->dirname = get_nth_dirname(dir, include_directories);
288
	    line->dirname = get_nth_dirname(dir, version, format, address_size, obj, include_directories);
275 289
	}
276 290
    }
277 291
}
278 292

  
279 293
static void
280 294
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
295
	  uint16_t version, uint8_t format, uint8_t address_size,
281 296
	  char *include_directories, char *filenames,
282 297
	  obj_info_t *obj, line_info_t *lines, int offset)
283 298
{
......
288 303
	/* We assume one line code doesn't result >100 bytes of native code.
289 304
       We may want more reliable way eventually... */
290 305
	if (addr < a && a < addr + 100) {
291
	    fill_filename(file, include_directories, filenames, &lines[i], obj);
306
	    fill_filename(file, version, format, address_size, include_directories, filenames, &lines[i], obj);
292 307
	    lines[i].line = line;
293 308
	}
294 309
    }
......
298 313
    uint64_t unit_length;
299 314
    uint16_t version;
300 315
    uint8_t format; /* 4 or 8 */
316
    uint8_t address_size;
317
    uint8_t segment_selector_size;
301 318
    uint64_t header_length;
302 319
    uint8_t minimum_instruction_length;
303 320
    uint8_t maximum_operations_per_instruction;
......
312 329
    const char *cu_end;
313 330
};
314 331

  
332
static int debug_line_header_skip_directories_5(char **, struct LineNumberProgramHeader *);
315 333
static int
316 334
parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
317 335
{
......
330 348

  
331 349
    header->version = *(uint16_t *)p;
332 350
    p += sizeof(uint16_t);
333
    if (header->version > 4) return -1;
351
    if (header->version > 5) return -1;
352

  
353
    if (header->version >= 5) {
354
	header->address_size = *(uint8_t *)p++;
355
	/* header->segment_selector_size = *(uint8_t *)p; */
356
	if (*p != 0) return -1;
357
	p++;
358
    } else {
359
	header->address_size = 0;
360
    }
334 361

  
335 362
    header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
336 363
    p += header->format;
......
357 384
    if (p >= header->cu_end) return -1;
358 385

  
359 386
    /* skip include directories */
360
    while (*p) {
361
	p = memchr(p, '\0', header->cu_end - p);
362
	if (!p) return -1;
387
    if (header->version >= 5) {
388
	if (debug_line_header_skip_directories_5((char **)&p, header)) return -1;
389
    } else {
390
	while (*p) {
391
	    p = memchr(p, '\0', header->cu_end - p);
392
	    if (!p) return -1;
393
	    p++;
394
	}
363 395
	p++;
364
    }
365
    p++;
396
    } 
366 397

  
367 398
    header->filenames = p;
368 399

  
......
397 428
#define FILL_LINE()						    \
398 429
    do {							    \
399 430
	fill_line(num_traces, traces, addr, file, line,		    \
431
		  header.version,				    \
432
		  header.format,				    \
433
		  header.address_size,				    \
400 434
                  (char *)header.include_directories,               \
401 435
                  (char *)header.filenames,                         \
402 436
		  obj, lines, offset);				    \
......
808 842
    DW_FORM_addrx4 = 0x2c
809 843
};
810 844

  
845
/* Content type codes */
846
enum
847
{
848
    DW_LNCT_path = 0x01,
849
    DW_LNCT_directory_index = 0x02,
850
    DW_LNCT_timestamp = 0x03,
851
    DW_LNCT_size = 0x04,
852
    DW_LNCT_MD5 = 0x05
853
};
854

  
811 855
enum {
812 856
    VAL_none = 0,
813 857
    VAL_cstr = 1,
......
822 866
    char *file;
823 867
    char *current_cu;
824 868
    uint64_t current_low_pc;
869
    uint16_t debug_line_version;
870
    uint8_t debug_line_format;
871
    uint8_t debug_line_address_size;
825 872
    char *debug_line_cu_end;
826 873
    char *debug_line_files;
827 874
    char *debug_line_directories;
......
1006 1053
    if (parse_debug_line_header(&p, &header))
1007 1054
        return -1;
1008 1055

  
1056
    reader->debug_line_version = header.version;
1057
    reader->debug_line_format = header.format;
1058
    reader->debug_line_address_size = header.address_size;
1009 1059
    reader->debug_line_cu_end = (char *)header.cu_end;
1010 1060
    reader->debug_line_directories = (char *)header.include_directories;
1011 1061
    reader->debug_line_files = (char *)header.filenames;
......
1053 1103
static const char *
1054 1104
get_cstr_value(DebugInfoValue *v)
1055 1105
{
1056
    if (v->as.ptr) {
1057
        return v->as.ptr + v->off;
1058
    } else {
1059
        return NULL;
1106
    switch (v->form) {
1107
      case DW_FORM_strp:
1108
	if (v->as.ptr) {
1109
	    return v->as.ptr + v->off;
1110
	} else {
1111
	    return NULL;
1112
	}
1113
      default:
1114
	return NULL;
1060 1115
    }
1061 1116
}
1062 1117

  
......
1578 1633
                line.sname = get_cstr_value(&v);
1579 1634
                break;
1580 1635
              case DW_AT_call_file:
1581
                fill_filename((int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1636
                fill_filename((int)v.as.uint64, reader->debug_line_version, reader->debug_line_format, reader->debug_line_address_size, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
1582 1637
                break;
1583 1638
              case DW_AT_call_line:
1584 1639
                line.line = (int)v.as.uint64;
......
1752 1807
                    ".debug_info",
1753 1808
                    ".debug_line",
1754 1809
                    ".debug_ranges",
1755
                    ".debug_str"
1810
                    ".debug_str",
1811
                    ".debug_line_str",
1756 1812
                };
1757 1813

  
1758 1814
                for (j=0; j < DWARF_SECTION_COUNT; j++) {
......
1817 1873
            if (di_read_cu(&reader)) goto use_symtab;
1818 1874
            debug_info_read(&reader, num_traces, traces, lines, offset);
1819 1875
        }
1876
        if (reader.debug_line_version >= 5) goto use_symtab;
1820 1877
    }
1821 1878
    else {
1822 1879
        /* This file doesn't have dwarf, use symtab or dynsym */
......
2008 2065
                    "__debug_info",
2009 2066
                    "__debug_line",
2010 2067
                    "__debug_ranges",
2011
                    "__debug_str"
2068
                    "__debug_str",
2069
                    "__debug_line_str",
2012 2070
                };
2013 2071
                struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;
2014 2072
                if (strcmp(scmd->segname, "__TEXT") == 0) {
......
2291 2349
    free(dladdr_fbases);
2292 2350
}
2293 2351

  
2352
static const char *
2353
get_nth_dirname_5(unsigned long dir, uint16_t version, uint8_t format, uint8_t address_size, obj_info_t *obj, char *p)
2354
{
2355
	const char *ret = "";
2356
	uint64_t i, j;
2357
	DebugInfoReader reader = {
2358
	    .format = format,
2359
	    .address_size = address_size,
2360
	    .p = p
2361
	};
2362
	uint8_t format_count = read_uint8(&reader.p);
2363
	uint64_t *content_types = calloc(format_count, sizeof(uint64_t)); 
2364
	uint64_t *forms = calloc(format_count, sizeof(uint64_t)); 
2365
	if (content_types == NULL || forms == NULL) return "";
2366
	for (i = 0; i < format_count; ++i) {
2367
	    content_types[i] = uleb128(&reader.p);
2368
	    forms[i] = uleb128(&reader.p);
2369
	}
2370
	uint64_t directories_count = uleb128(&reader.p);
2371
	DebugInfoValue v = {{}};
2372
	for (j = 0; j < directories_count; ++j) {
2373
	    for (i = 0; i < format_count; ++i) {
2374
		debug_info_reader_read_value(&reader, forms[i], &v);
2375
		if (j == dir && content_types[i] == DW_LNCT_path) {
2376
		    switch (forms[i]) {
2377
		      case DW_FORM_line_strp:
2378
			ret = &obj->debug_line_str.ptr[v.as.uint64];
2379
			break;
2380
		    }
2381
		}
2382
	    }
2383
	}
2384
	free(forms);
2385
	free(content_types);
2386
	return ret;
2387
}
2388

  
2389
static void
2390
fill_filename_5(int file, uint16_t version, uint8_t format, uint8_t address_size, char *include_directories, char *filenames, line_info_t *line, obj_info_t *obj)
2391
{
2392
	char *p = filenames;
2393
	unsigned long dir;
2394

  
2395
	uint64_t i, j;
2396
	DebugInfoReader reader = {
2397
	    .format = format,
2398
	    .address_size = address_size,
2399
	    .p = p
2400
	};
2401
	uint8_t format_count = read_uint8(&reader.p);
2402
	uint64_t *content_types = calloc(format_count, sizeof(uint64_t)); 
2403
	uint64_t *forms = calloc(format_count, sizeof(uint64_t)); 
2404
	if (content_types == NULL || forms == NULL) return;
2405
	for (i = 0; i < format_count; ++i) {
2406
	    content_types[i] = uleb128(&reader.p);
2407
	    forms[i] = uleb128(&reader.p);
2408
	}
2409
	uint64_t file_names_count = uleb128(&reader.p);
2410
	DebugInfoValue v = {{}};
2411
	for (j = 0; j < file_names_count; ++j) {
2412
	    for (i = 0; i < format_count; ++i) {
2413
		debug_info_reader_read_value(&reader, forms[i], &v);
2414
		if ((int)j == file) {
2415
		    switch (content_types[i]) {
2416
		      case DW_LNCT_path:
2417
			switch (forms[i]) {
2418
			  case DW_FORM_line_strp:
2419
			    line->filename = &obj->debug_line_str.ptr[v.as.uint64];
2420
			    break;
2421
			}
2422
			break;
2423
		      case DW_LNCT_directory_index:
2424
			switch (forms[i]) {
2425
			  case DW_FORM_udata:
2426
			    dir = v.as.uint64;
2427
			    break;
2428
			}
2429
			break;
2430
		    }
2431
		}
2432
	    }
2433
	}
2434
	free(forms);
2435
	free(content_types);
2436
	line->dirname = get_nth_dirname_5(dir, version, format, address_size, obj, include_directories);
2437
	return;
2438
}
2439

  
2440
static int
2441
debug_line_header_skip_directories_5(char **p, struct LineNumberProgramHeader *header)
2442
{
2443
	uint64_t i, j;
2444
	DebugInfoReader reader = {
2445
	    .format = header->format,
2446
	    .address_size = header->address_size,
2447
	    .p = *p
2448
	};
2449
	uint8_t format_count = read_uint8(&reader.p);
2450
	uint64_t *forms = calloc(format_count, sizeof(uint64_t)); 
2451
	if (forms == NULL) return -1;
2452
	for (i = 0; i < format_count; ++i) {
2453
	    uleb128(&reader.p); /* content type code */
2454
	    forms[i] = uleb128(&reader.p);
2455
	}
2456
	uint64_t directories_count = uleb128(&reader.p);
2457
	DebugInfoValue v = {{}};
2458
	for (j = 0; j < directories_count; ++j) {
2459
	    for (i = 0; i < format_count; ++i) {
2460
		debug_info_reader_read_value(&reader, forms[i], &v);
2461
	    }
2462
	}
2463
	free(forms);
2464
	*p = reader.p;
2465
	return 0;
2466
}
2467

  
2294 2468
/* From FreeBSD's lib/libstand/printf.c */
2295 2469
/*-
2296 2470
 * Copyright (c) 1986, 1988, 1991, 1993