13 read_debuglink (Elf *elf)
17 GElf_Shdr section_header;
19 unsigned char *section_strtab;
21 if (gelf_getehdr (elf, &ehdr) == NULL)
23 printf ("Not an elf binary, exiting\n");
27 /* Locate section header strtab */
28 section = elf_getscn (elf, ehdr.e_shstrndx);
29 data = elf_getdata (section, NULL);
30 section_strtab = data->d_buf;
33 while ((section = elf_nextscn (elf, section)) != NULL)
37 gelf_getshdr (section, §ion_header);
39 section_name = section_strtab + section_header.sh_name;
41 if (strcmp (section_name, DEBUGLINKNAME) == 0)
43 data = elf_rawdata (section, NULL);
44 return debug_link_from_data (elf, data);
51 find_section (Elf *elf, const unsigned char *name, const unsigned char *strtab)
54 GElf_Shdr section_header;
55 const unsigned char *section_name;
58 while ((section = elf_nextscn (elf, section)) != NULL)
61 gelf_getshdr (section, §ion_header);
63 section_name = strtab + section_header.sh_name;
65 if (strcmp (section_name, name) == 0)
73 find_in_strtab (char *name, char *strtab, size_t strtab_len)
77 name_len = strlen (name);
79 for (i = 0; i < strtab_len - (name_len + 1); i++)
80 if (strcmp (strtab+i, name) == 0)
86 unstrip_file (Elf *elf, Elf *debug_elf, Elf *out_elf)
89 GElf_Ehdr ehdr, debug_ehdr;
91 GElf_Shdr section_header;
92 Elf_Scn *section, *out_section;
93 Elf_Data *data, *out_data;
94 unsigned char *section_strtab;
95 size_t section_strtab_len;
96 unsigned char *debug_section_strtab;
97 size_t debug_section_strtab_len;
98 size_t *debug_section_map;
99 size_t *stripped_section_map;
102 size_t new_strtab_index;
104 elf_flagelf (out_elf, ELF_C_SET, ELF_F_LAYOUT);
106 gelf_getehdr (elf, &ehdr);
107 if (gelf_getehdr (debug_elf, &debug_ehdr) == NULL)
109 printf ("debug file not an elf binary, exiting\n");
113 /* copy elf header: */
114 gelf_newehdr (out_elf, ehdr.e_ident[EI_CLASS]);
115 gelf_update_ehdr (out_elf, &ehdr);
117 /* Copy program headers: */
118 gelf_newphdr (out_elf, ehdr.e_phnum);
120 for (i = 0; i < ehdr.e_phnum; i++)
122 gelf_getphdr (elf, i, &phdr);
123 gelf_update_phdr(out_elf, i, &phdr);
126 /* Locate section header strtabs */
127 section = elf_getscn (elf, ehdr.e_shstrndx);
128 data = elf_getdata (section, NULL);
129 section_strtab = data->d_buf;
130 section_strtab_len = data->d_size;
132 section = elf_getscn (debug_elf, debug_ehdr.e_shstrndx);
133 data = elf_getdata (section, NULL);
134 debug_section_strtab = data->d_buf;
135 debug_section_strtab_len = data->d_size;
137 /* Read unlinkinfo */
139 section = find_section (debug_elf, UNSTRIPINFONAME, debug_section_strtab);
142 data = elf_rawdata (section, NULL);
143 info = unstrip_info_from_data (elf, data);
148 printf ("Can't find unstrip info in debug file\n");
152 /* Construct backward section index maps */
153 debug_section_map = calloc (info->n_sections, sizeof (size_t));
154 for (i = 0; i < info->n_sections; i++)
156 if (info->sections[i].debug_section > 0)
157 debug_section_map[info->sections[i].debug_section] = i;
160 stripped_section_map = calloc (ehdr.e_shnum, sizeof (size_t));
162 while ((section = elf_nextscn(elf, section)) != NULL)
164 gelf_getshdr (section, §ion_header);
165 section_name = section_strtab + section_header.sh_name;
167 for (i = 0; i < info->n_sections; i++)
169 char *debug_section_name;
171 debug_section_name = debug_section_strtab + info->sections[i].name;
173 /* If section name is same as an original section, and the original
174 * section is not in debugfile, use this section */
175 if (info->sections[i].debug_section == 0 &&
176 strcmp (debug_section_name, section_name) == 0)
178 stripped_section_map[elf_ndxscn(section)] = i;
184 /* combine sections */
185 new_strtab_index = 0;
186 for (i = 0; i < info->n_sections; i++)
188 if (info->sections[i].debug_section != 0)
190 section = elf_getscn(debug_elf, info->sections[i].debug_section);
192 out_section = elf_newscn(out_elf);
194 /* Copy section header */
195 gelf_getshdr (section, §ion_header);
196 section_header.sh_offset = info->sections[i].orig_offset;
197 section_header.sh_link = debug_section_map[section_header.sh_link];
198 if (section_header.sh_type == SHT_REL ||
199 section_header.sh_type == SHT_RELA)
200 section_header.sh_info = stripped_section_map[section_header.sh_info];
204 while ((data = elf_rawdata (section, data)))
206 out_data = elf_newdata (out_section);
208 /* TODO: remove .unstripinfo for shstrtab */
210 out_data->d_buf = data->d_buf;
211 out_data->d_type = data->d_type;
212 out_data->d_size = data->d_size;
213 if (debug_ehdr.e_shstrndx == info->sections[i].debug_section)
215 new_strtab_index = i;
216 if (strcmp (data->d_buf + data->d_size - (strlen(UNSTRIPINFONAME) + 1), UNSTRIPINFONAME) == 0)
218 out_data->d_size -= strlen(UNSTRIPINFONAME) + 1;
219 section_header.sh_size = out_data->d_size;
222 out_data->d_off = data->d_off;
223 out_data->d_align = section_header.sh_addralign;
224 out_data->d_version = data->d_version;
226 gelf_update_shdr(out_section, §ion_header);
230 section_name = debug_section_strtab + info->sections[i].name;
231 section = find_section (elf, section_name, section_strtab);
235 out_section = elf_newscn(out_elf);
237 /* Copy section header */
238 gelf_getshdr (section, §ion_header);
239 section_header.sh_offset = info->sections[i].orig_offset;
240 section_header.sh_link = stripped_section_map[section_header.sh_link];
241 if (section_header.sh_type == SHT_REL ||
242 section_header.sh_type == SHT_RELA)
243 section_header.sh_info = stripped_section_map[section_header.sh_info];
244 section_header.sh_name = find_in_strtab (section_name, debug_section_strtab, debug_section_strtab_len);
245 gelf_update_shdr (out_section, §ion_header);
249 while ((data = elf_rawdata (section, data)))
251 out_data = elf_newdata (out_section);
253 out_data->d_buf = data->d_buf;
254 out_data->d_type = data->d_type;
255 out_data->d_size = data->d_size;
256 out_data->d_off = data->d_off;
257 out_data->d_align = section_header.sh_addralign;
258 out_data->d_version = data->d_version;
264 gelf_getehdr (out_elf, &ehdr);
265 ehdr.e_shstrndx = new_strtab_index;
266 ehdr.e_shoff = info->orig_e_shoff;
267 gelf_update_ehdr (out_elf, &ehdr);
272 main (int argc, char *argv[])
274 Elf *elf, *debug_elf, *out_elf;
275 int fd, debug_fd, out;
276 char *origname, *unstrippedname;
277 DebugLink *debuglink;
279 if (elf_version(EV_CURRENT) == EV_NONE)
281 printf ("library out of date\n");
287 printf ("usage: unstriptofile filename\n");
293 fd = open (origname, O_RDONLY);
296 printf ("Failed to open input file\n");
300 elf = elf_begin (fd, ELF_C_READ, NULL);
303 printf ("Failed to elf_begin input file\n");
307 debuglink = read_debuglink (elf);
308 if (debuglink == NULL)
310 printf ("Cannot find .debuglink section in input file\n");
314 if (debuglink->checksum != crc32_file (debuglink->filename))
316 printf ("Invalid checksum for debug file. File has been modified.\n");
320 debug_fd = open (debuglink->filename, O_RDONLY);
323 printf ("Failed to open debug file\n");
327 debug_elf = elf_begin (debug_fd, ELF_C_READ, NULL);
328 if (debug_elf == NULL)
330 printf ("Failed to elf_begin debug file\n");
334 unstrippedname = malloc (strlen (origname) + strlen (".unstripped") + 1);
335 strcpy (unstrippedname, origname);
336 strcat (unstrippedname, ".unstripped");
338 out = open (unstrippedname, O_RDWR | O_TRUNC | O_CREAT, 0644);
341 printf ("Failed to open output file\n");
345 out_elf = elf_begin (out, ELF_C_WRITE, NULL);
348 printf ("Failed to elf_begin output file\n");
352 unstrip_file (elf, debug_elf, out_elf);
354 elf_update (out_elf, ELF_C_WRITE);