1 /* Needed for libelf */
2 #define _FILE_OFFSET_BITS 64
16 read_debuglink (Elf *elf)
20 GElf_Shdr section_header;
22 unsigned char *section_strtab;
24 if (gelf_getehdr (elf, &ehdr) == NULL)
26 printf ("Not an elf binary, exiting\n");
30 /* Locate section header strtab */
31 section = elf_getscn (elf, ehdr.e_shstrndx);
32 data = elf_getdata (section, NULL);
33 section_strtab = data->d_buf;
36 while ((section = elf_nextscn (elf, section)) != NULL)
40 gelf_getshdr (section, §ion_header);
42 section_name = section_strtab + section_header.sh_name;
44 if (strcmp (section_name, DEBUGLINKNAME) == 0)
46 data = elf_rawdata (section, NULL);
47 return debug_link_from_data (elf, data);
54 find_section (Elf *elf, const unsigned char *name, const unsigned char *strtab)
57 GElf_Shdr section_header;
58 const unsigned char *section_name;
61 while ((section = elf_nextscn (elf, section)) != NULL)
64 gelf_getshdr (section, §ion_header);
66 section_name = strtab + section_header.sh_name;
68 if (strcmp (section_name, name) == 0)
76 find_in_strtab (char *name, char *strtab, size_t strtab_len)
80 name_len = strlen (name);
82 for (i = 0; i < strtab_len - (name_len + 1); i++)
83 if (strcmp (strtab+i, name) == 0)
89 unstrip_file (Elf *elf, Elf *debug_elf, Elf *out_elf)
92 GElf_Ehdr ehdr, debug_ehdr;
94 GElf_Shdr section_header;
95 Elf_Scn *section, *out_section;
96 Elf_Data *data, *out_data;
97 unsigned char *section_strtab;
98 size_t section_strtab_len;
99 unsigned char *debug_section_strtab;
100 size_t debug_section_strtab_len;
101 size_t *debug_section_map;
102 size_t *stripped_section_map;
105 size_t new_strtab_index;
107 elf_flagelf (out_elf, ELF_C_SET, ELF_F_LAYOUT);
109 gelf_getehdr (elf, &ehdr);
110 if (gelf_getehdr (debug_elf, &debug_ehdr) == NULL)
112 printf ("debug file not an elf binary, exiting\n");
116 /* copy elf header: */
117 gelf_newehdr (out_elf, ehdr.e_ident[EI_CLASS]);
118 gelf_update_ehdr (out_elf, &ehdr);
120 /* Copy program headers: */
121 gelf_newphdr (out_elf, ehdr.e_phnum);
123 for (i = 0; i < ehdr.e_phnum; i++)
125 gelf_getphdr (elf, i, &phdr);
126 gelf_update_phdr(out_elf, i, &phdr);
129 /* Locate section header strtabs */
130 section = elf_getscn (elf, ehdr.e_shstrndx);
131 data = elf_getdata (section, NULL);
132 section_strtab = data->d_buf;
133 section_strtab_len = data->d_size;
135 section = elf_getscn (debug_elf, debug_ehdr.e_shstrndx);
136 data = elf_getdata (section, NULL);
137 debug_section_strtab = data->d_buf;
138 debug_section_strtab_len = data->d_size;
140 /* Read unlinkinfo */
142 section = find_section (debug_elf, UNSTRIPINFONAME, debug_section_strtab);
145 data = elf_rawdata (section, NULL);
146 info = unstrip_info_from_data (elf, data);
151 printf ("Can't find unstrip info in debug file\n");
155 /* Construct backward section index maps */
156 debug_section_map = calloc (info->n_sections, sizeof (size_t));
157 for (i = 0; i < info->n_sections; i++)
159 if (info->sections[i].debug_section > 0)
160 debug_section_map[info->sections[i].debug_section] = i;
163 stripped_section_map = calloc (ehdr.e_shnum, sizeof (size_t));
165 while ((section = elf_nextscn(elf, section)) != NULL)
167 gelf_getshdr (section, §ion_header);
168 section_name = section_strtab + section_header.sh_name;
170 for (i = 0; i < info->n_sections; i++)
172 char *debug_section_name;
174 debug_section_name = debug_section_strtab + info->sections[i].name;
176 /* If section name is same as an original section, and the original
177 * section is not in debugfile, use this section */
178 if (info->sections[i].debug_section == 0 &&
179 strcmp (debug_section_name, section_name) == 0)
181 stripped_section_map[elf_ndxscn(section)] = i;
187 /* combine sections */
188 new_strtab_index = 0;
189 for (i = 0; i < info->n_sections; i++)
191 if (info->sections[i].debug_section != 0)
193 section = elf_getscn(debug_elf, info->sections[i].debug_section);
195 out_section = elf_newscn(out_elf);
197 /* Copy section header */
198 gelf_getshdr (section, §ion_header);
199 section_header.sh_offset = info->sections[i].orig_offset;
200 section_header.sh_link = debug_section_map[section_header.sh_link];
201 if (section_header.sh_type == SHT_REL ||
202 section_header.sh_type == SHT_RELA)
203 section_header.sh_info = stripped_section_map[section_header.sh_info];
207 while ((data = elf_rawdata (section, data)))
209 out_data = elf_newdata (out_section);
211 /* TODO: remove .unstripinfo for shstrtab */
213 out_data->d_buf = data->d_buf;
214 out_data->d_type = data->d_type;
215 out_data->d_size = data->d_size;
216 if (debug_ehdr.e_shstrndx == info->sections[i].debug_section)
218 new_strtab_index = i;
219 if (strcmp (data->d_buf + data->d_size - (strlen(UNSTRIPINFONAME) + 1), UNSTRIPINFONAME) == 0)
221 out_data->d_size -= strlen(UNSTRIPINFONAME) + 1;
222 section_header.sh_size = out_data->d_size;
225 out_data->d_off = data->d_off;
226 out_data->d_align = section_header.sh_addralign;
227 out_data->d_version = data->d_version;
229 gelf_update_shdr(out_section, §ion_header);
233 section_name = debug_section_strtab + info->sections[i].name;
234 section = find_section (elf, section_name, section_strtab);
238 out_section = elf_newscn(out_elf);
240 /* Copy section header */
241 gelf_getshdr (section, §ion_header);
242 section_header.sh_offset = info->sections[i].orig_offset;
243 section_header.sh_link = stripped_section_map[section_header.sh_link];
244 if (section_header.sh_type == SHT_REL ||
245 section_header.sh_type == SHT_RELA)
246 section_header.sh_info = stripped_section_map[section_header.sh_info];
247 section_header.sh_name = find_in_strtab (section_name, debug_section_strtab, debug_section_strtab_len);
248 gelf_update_shdr (out_section, §ion_header);
252 while ((data = elf_rawdata (section, data)))
254 out_data = elf_newdata (out_section);
256 out_data->d_buf = data->d_buf;
257 out_data->d_type = data->d_type;
258 out_data->d_size = data->d_size;
259 out_data->d_off = data->d_off;
260 out_data->d_align = section_header.sh_addralign;
261 out_data->d_version = data->d_version;
267 gelf_getehdr (out_elf, &ehdr);
268 ehdr.e_shstrndx = new_strtab_index;
269 ehdr.e_shoff = info->orig_e_shoff;
270 gelf_update_ehdr (out_elf, &ehdr);
275 main (int argc, char *argv[])
277 Elf *elf, *debug_elf, *out_elf;
278 int fd, debug_fd, out;
279 char *origname, *unstrippedname;
280 DebugLink *debuglink;
282 if (elf_version(EV_CURRENT) == EV_NONE)
284 printf ("library out of date\n");
290 printf ("usage: unstriptofile filename\n");
296 fd = open (origname, O_RDONLY);
299 printf ("Failed to open input file\n");
303 elf = elf_begin (fd, ELF_C_READ, NULL);
306 printf ("Failed to elf_begin input file\n");
310 debuglink = read_debuglink (elf);
311 if (debuglink == NULL)
313 printf ("Cannot find .debuglink section in input file\n");
317 if (debuglink->checksum != crc32_file (debuglink->filename))
319 printf ("Invalid checksum for debug file. File has been modified.\n");
323 debug_fd = open (debuglink->filename, O_RDONLY);
326 printf ("Failed to open debug file\n");
330 debug_elf = elf_begin (debug_fd, ELF_C_READ, NULL);
331 if (debug_elf == NULL)
333 printf ("Failed to elf_begin debug file\n");
337 unstrippedname = malloc (strlen (origname) + strlen (".unstripped") + 1);
338 strcpy (unstrippedname, origname);
339 strcat (unstrippedname, ".unstripped");
341 out = open (unstrippedname, O_RDWR | O_TRUNC | O_CREAT, 0644);
344 printf ("Failed to open output file\n");
348 out_elf = elf_begin (out, ELF_C_WRITE, NULL);
351 printf ("Failed to elf_begin output file\n");
355 unstrip_file (elf, debug_elf, out_elf);
357 elf_update (out_elf, ELF_C_WRITE);