diff --git a/tools/debugedit.c b/tools/debugedit.c index b9db7db..820e5aa 100644 --- a/tools/debugedit.c +++ b/tools/debugedit.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009, 2010 Red Hat, Inc. Written by Alexander Larsson , 2002 Based on code by Jakub Jelinek , 2001. @@ -444,16 +444,24 @@ has_prefix (const char *str, { size_t str_len; size_t prefix_len; - + str_len = strlen (str); prefix_len = strlen (prefix); if (str_len < prefix_len) return 0; - + return strncmp (str, prefix, prefix_len) == 0; } +static int dirty_elf; +static void +dirty_section (unsigned int sec) +{ + elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); + dirty_elf = 1; +} + static int edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) { @@ -468,9 +476,9 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) if (phase != 0) return 0; - + ptr += off; - + endcu = ptr + 4; endcu += read_32 (ptr); if (endcu == ptr + 0xffffffff) @@ -493,7 +501,7 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) value); return 1; } - + endprol = ptr + 4; endprol += read_32 (ptr); if (endprol > endcu) @@ -502,10 +510,10 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) dso->filename); return 1; } - + opcode_base = ptr[4]; ptr = dir = ptr + 4 + opcode_base; - + /* dir table: */ value = 1; while (*ptr != 0) @@ -600,12 +608,12 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) } free (s); - + read_uleb128 (ptr); read_uleb128 (ptr); } ++ptr; - + if (dest_dir) { unsigned char *srcptr, *buf = NULL; @@ -628,14 +636,16 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) size_t len = strlen ((char *)srcptr) + 1; const unsigned char *readptr = srcptr; + char *orig = strdup ((const char *) srcptr); + if (*srcptr == '/' && has_prefix ((char *)srcptr, base_dir)) { if (dest_len < base_len) - ++abs_dir_cnt; + ++abs_dir_cnt; memcpy (ptr, dest_dir, dest_len); ptr += dest_len; readptr += base_len; - } + } srcptr += len; shrank += srcptr - readptr; @@ -644,9 +654,10 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) shrank -= len; ptr += len; - elf_flagdata (debug_sections[DEBUG_STR].elf_data, - ELF_C_SET, ELF_F_DIRTY); - } + if (memcmp (orig, ptr - len, len)) + dirty_section (DEBUG_STR); + free (orig); + } if (shrank > 0) { @@ -654,7 +665,7 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) error (EXIT_FAILURE, 0, "canonicalization unexpectedly shrank by one character"); else - { + { memset (ptr, 'X', shrank); ptr += shrank; *ptr++ = '\0'; @@ -687,8 +698,7 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) len - base_len); ptr += dest_len - base_len; } - elf_flagdata (debug_sections[DEBUG_STR].elf_data, - ELF_C_SET, ELF_F_DIRTY); + dirty_section (DEBUG_STR); } else if (ptr != srcptr) memmove (ptr, srcptr, len); @@ -708,8 +718,6 @@ edit_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir, int phase) return 0; } - - static unsigned char * edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) { @@ -717,7 +725,7 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) uint32_t list_offs; int found_list_offs; char *comp_dir; - + comp_dir = NULL; list_offs = 0; found_list_offs = 0; @@ -726,7 +734,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) uint32_t form = t->attr[i].form; size_t len = 0; size_t base_len, dest_len; - while (1) { @@ -740,56 +747,53 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) } if (t->attr[i].attr == DW_AT_comp_dir) - { - if ( form == DW_FORM_string ) - { + { + if (form == DW_FORM_string) + { free (comp_dir); comp_dir = strdup ((char *)ptr); - + if (phase == 1 && dest_dir && has_prefix ((char *)ptr, base_dir)) - { + { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (ptr, dest_dir, dest_len); if (dest_len < base_len) - { + { memset(ptr + dest_len, '/', base_len - dest_len); - - } - elf_flagdata (debug_sections[DEBUG_INFO].elf_data, - ELF_C_SET, ELF_F_DIRTY); - } - } - + + } + dirty_section (DEBUG_INFO); + } + } else if (form == DW_FORM_strp && debug_sections[DEBUG_STR].data) - { + { char *dir; dir = (char *) debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); + + do_read_32_relocated (ptr); free (comp_dir); comp_dir = strdup (dir); if (phase == 1 && dest_dir && has_prefix (dir, base_dir)) - { + { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (dir, dest_dir, dest_len); if (dest_len < base_len) - { + { memmove (dir + dest_len, dir + base_len, strlen (dir + base_len) + 1); - } - elf_flagdata (debug_sections[DEBUG_STR].elf_data, - ELF_C_SET, ELF_F_DIRTY); - } - } - } + } + dirty_section (DEBUG_STR); + } + } + } else if ((t->tag == DW_TAG_compile_unit || t->tag == DW_TAG_partial_unit) && t->attr[i].attr == DW_AT_name @@ -797,9 +801,9 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) && debug_sections[DEBUG_STR].data) { char *name; - + name = (char *) debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); + + do_read_32_relocated (ptr); if (*name == '/' && comp_dir == NULL) { char *enddir = strrchr (name, '/'); @@ -818,15 +822,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) { base_len = strlen (base_dir); dest_len = strlen (dest_dir); - + memcpy (name, dest_dir, dest_len); if (dest_len < base_len) { memmove (name + dest_len, name + base_len, strlen (name + base_len) + 1); } - elf_flagdata (debug_sections[DEBUG_STR].elf_data, - ELF_C_SET, ELF_F_DIRTY); + dirty_section (DEBUG_STR); } } @@ -896,7 +899,7 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) if (form == DW_FORM_block1) ptr += len; - + break; } } @@ -985,7 +988,7 @@ edit_dwarf2 (DSO *dso) return 1; } - scn = dso->scn[i]; + scn = dso->scn[i]; data = elf_rawdata (scn, NULL); assert (data != NULL && data->d_buf != NULL); assert (elf_rawdata (scn, data) == NULL); @@ -1061,7 +1064,7 @@ edit_dwarf2 (DSO *dso) int rtype; i = debug_sections[DEBUG_INFO].relsec; - scn = dso->scn[i]; + scn = dso->scn[i]; data = elf_getdata (scn, NULL); assert (data != NULL && data->d_buf != NULL); assert (elf_getdata (scn, data) == NULL); @@ -1179,13 +1182,13 @@ edit_dwarf2 (DSO *dso) error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); return 1; } - + if (endcu > endsec) { error (0, 0, "%s: .debug_info too small", dso->filename); return 1; } - + cu_version = read_16 (ptr); if (cu_version != 2 && cu_version != 3) { @@ -1193,7 +1196,7 @@ edit_dwarf2 (DSO *dso) cu_version); return 1; } - + value = read_32_relocated (ptr); if (value >= debug_sections[DEBUG_ABBREV].size) { @@ -1204,7 +1207,7 @@ edit_dwarf2 (DSO *dso) dso->filename); return 1; } - + if (ptr_size == 0) { ptr_size = read_1 (ptr); @@ -1221,12 +1224,12 @@ edit_dwarf2 (DSO *dso) dso->filename); return 1; } - + abbrev = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value); if (abbrev == NULL) return 1; - + while (ptr < endcu) { tag.entry = read_uleb128 (ptr); @@ -1240,18 +1243,18 @@ edit_dwarf2 (DSO *dso) htab_delete (abbrev); return 1; } - + ptr = edit_attributes (dso, ptr, t, phase); if (ptr == NULL) break; } - + htab_delete (abbrev); } } free (relbuf); } - + return 0; } @@ -1314,7 +1317,7 @@ fdopen_dso (int fd, const char *name) } elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); - + memset (dso, 0, sizeof(DSO)); dso->elf = elf; dso->ehdr = ehdr; @@ -1368,6 +1371,9 @@ handle_build_id (DSO *dso, Elf_Data *build_id, exit (1); } + if (!dirty_elf) + goto print; + if (elf_update (dso->elf, ELF_C_NULL) < 0) { fprintf (stderr, "Failed to update file: %s\n", @@ -1447,6 +1453,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id, elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY); + print: /* Now format the build ID bits in hex to print out. */ { const uint8_t * id = (uint8_t *)build_id->d_buf + build_id_offset; @@ -1471,7 +1478,7 @@ main (int argc, char *argv[]) size_t build_id_offset = 0, build_id_size = 0; optCon = poptGetContext("debugedit", argc, (const char **)argv, optionsTable, 0); - + while ((nextopt = poptGetNextOpt (optCon)) > 0 || nextopt == POPT_ERROR_BADOPT) /* do nothing */ ; @@ -1483,7 +1490,7 @@ main (int argc, char *argv[]) argv[0]); exit (1); } - + args = poptGetArgs (optCon); if (args == NULL || args[0] == NULL || args[1] != NULL) { @@ -1522,12 +1529,12 @@ main (int argc, char *argv[]) free (dest_dir); dest_dir = p; } - + if (list_file != NULL) { list_file_fd = open (list_file, O_WRONLY|O_CREAT|O_APPEND, 0644); } - + file = args[0]; if (elf_version(EV_CURRENT) == EV_NONE) @@ -1559,7 +1566,7 @@ main (int argc, char *argv[]) for (i = 1; i < dso->ehdr.e_shnum; i++) { const char *name; - + switch (dso->shdr[i].sh_type) { case SHT_PROGBITS: @@ -1588,7 +1595,7 @@ main (int argc, char *argv[]) Elf_Data src = dst; src.d_buf = data->d_buf; assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); - while ((char *) data->d_buf + data->d_size - + while ((char *) data->d_buf + data->d_size - (char *) src.d_buf > (int) sizeof nh && elf32_xlatetom (&dst, &src, dso->ehdr.e_ident[EI_DATA])) { @@ -1599,7 +1606,7 @@ main (int argc, char *argv[]) && !memcmp ((char *) src.d_buf + sizeof nh, "GNU", sizeof "GNU")) { build_id = data; - build_id_offset = (char *) src.d_buf + len - + build_id_offset = (char *) src.d_buf + len - (char *) data->d_buf; build_id_size = nh.n_descsz; break; @@ -1633,7 +1640,7 @@ main (int argc, char *argv[]) /* Restore old access rights */ chmod (file, stat_buf.st_mode); - + poptFreeContext (optCon); return 0;