c58393253c4c269eca05a7e1ba9c53b81bd91b5c
[platform/upstream/rpm.git] / tools / sections.c
1 #include "system.h"
2
3 #include "sections.h"
4 #include "utils.h"
5
6 #include "debug.h"
7
8 typedef struct {
9   Elf32_Word debug_section; 
10   Elf32_Word name; 
11   Elf32_Off orig_offset;
12 } UnstripInfoSection32;
13
14 typedef struct {
15   Elf64_Word debug_section; 
16   Elf64_Word name; 
17   Elf64_Off orig_offset;
18 } UnstripInfoSection64;
19
20 typedef struct {
21   Elf32_Off orig_e_shoff;
22   Elf32_Off n_sections;
23   UnstripInfoSection32 sections[1];
24 } UnstripInfo32;
25
26 typedef struct {
27   Elf64_Off orig_e_shoff;
28   Elf64_Off n_sections;
29   UnstripInfoSection64 sections[1];
30 } UnstripInfo64;
31
32 static uint32_t
33 elf_32_to_file (uint32_t x, int file_is_little_endian)
34 {
35   volatile uint32_t out;
36   unsigned char *outbytes;
37
38   outbytes = (unsigned char *)&out;
39   if (file_is_little_endian)
40     {
41       outbytes[0] = (x >> 0) & 0xff;
42       outbytes[1] = (x >> 8) & 0xff;
43       outbytes[2] = (x >> 16) & 0xff;
44       outbytes[3] = (x >> 24) & 0xff;
45     }
46   else /* big endian */
47     {
48       outbytes[0] = (x >> 24) & 0xff;
49       outbytes[1] = (x >> 16) & 0xff;
50       outbytes[2] = (x >> 8) & 0xff;
51       outbytes[3] = (x >> 0) & 0xff;
52     }
53   
54   return out;
55 }
56
57 static uint64_t
58 elf_64_to_file (uint64_t x, int file_is_little_endian)
59 {
60   volatile uint64_t out;
61   unsigned char *outbytes;
62   int i;
63
64   outbytes = (unsigned char *)&out;
65   if (file_is_little_endian)
66     {
67       for (i = 0; i < 8; i++)
68         outbytes[i] = (x >> (8*i)) & 0xff;
69     }
70   else /* big endian */
71     {
72       for (i = 0; i < 8; i++)
73         outbytes[7-i] = (x >> (8*i)) & 0xff;
74     }
75   
76   return out;
77 }
78
79 static Elf32_Word
80 word32_to_file (Elf32_Word x, Elf *elf)
81 {
82   Elf32_Ehdr *ehdr = elf32_getehdr (elf);
83   return elf_32_to_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
84 }
85
86 static Elf32_Off
87 off32_to_file (Elf32_Off x, Elf *elf)
88 {
89   Elf32_Ehdr *ehdr = elf32_getehdr (elf);
90   return elf_32_to_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
91 }
92
93 static Elf64_Word
94 word64_to_file (Elf64_Word x, Elf *elf)
95 {
96   Elf64_Ehdr *ehdr = elf64_getehdr (elf);
97   return elf_32_to_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
98 }
99
100 static Elf64_Off
101 off64_to_file (Elf64_Off x, Elf *elf)
102 {
103   Elf64_Ehdr *ehdr = elf64_getehdr (elf);
104   return elf_64_to_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
105 }
106
107 static uint32_t
108 elf_32_from_file (uint32_t x, int file_is_little_endian)
109 {
110   unsigned char *inbytes;
111
112   inbytes = (unsigned char *)&x;
113   if (file_is_little_endian)
114     {
115       return 
116         (inbytes[0] << 0) |
117         (inbytes[1] << 8) |
118         (inbytes[2] << 16) |
119         (inbytes[3] << 24);
120     }
121   else /* big endian */
122     {
123       return 
124         (inbytes[0] << 24) |
125         (inbytes[1] << 16) |
126         (inbytes[2] << 8) |
127         (inbytes[3] << 0);
128     }
129 }
130
131 static uint64_t
132 elf_64_from_file (uint64_t x, int file_is_little_endian)
133 {
134   unsigned char *inbytes;
135
136   inbytes = (unsigned char *)&x;
137   if (file_is_little_endian)
138     {
139       return 
140         ((uint64_t)inbytes[0] << 0) |
141         ((uint64_t)inbytes[1] << 8) |
142         ((uint64_t)inbytes[2] << 16) |
143         ((uint64_t)inbytes[3] << 24) |
144         ((uint64_t)inbytes[4] << 32) |
145         ((uint64_t)inbytes[5] << 40) |
146         ((uint64_t)inbytes[6] << 48) |
147         ((uint64_t)inbytes[7] << 56);
148     }
149   else /* big endian */
150     {
151       return 
152         ((uint64_t)inbytes[0] << 56) |
153         ((uint64_t)inbytes[1] << 48) |
154         ((uint64_t)inbytes[2] << 40) |
155         ((uint64_t)inbytes[3] << 32) |
156         ((uint64_t)inbytes[4] << 24) |
157         ((uint64_t)inbytes[5] << 16) |
158         ((uint64_t)inbytes[6] << 8) |
159         ((uint64_t)inbytes[7] << 0);
160     }
161 }
162
163 static Elf32_Word
164 word32_from_file (Elf32_Word x, Elf *elf)
165 {
166   Elf32_Ehdr *ehdr = elf32_getehdr (elf);
167   return elf_32_from_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
168 }
169
170 static Elf32_Off
171 off32_from_file (Elf32_Off x, Elf *elf)
172 {
173   Elf32_Ehdr *ehdr = elf32_getehdr (elf);
174   return elf_32_from_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
175 }
176
177 static Elf64_Word
178 word64_from_file (Elf64_Word x, Elf *elf)
179 {
180   Elf64_Ehdr *ehdr = elf64_getehdr (elf);
181   return elf_32_from_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
182 }
183
184 static Elf64_Off
185 off64_from_file (Elf64_Off x, Elf *elf)
186 {
187   Elf64_Ehdr *ehdr = elf64_getehdr (elf);
188   return elf_64_from_file (x, ehdr->e_ident[EI_DATA] & ELFDATA2LSB);
189 }
190
191 static void
192 unstrip_info_to_data32 (UnstripInfo *info,
193                         Elf *elf,
194                         Elf_Data *data)
195 {
196   UnstripInfo32 *info32;
197   int i;
198   
199   data->d_align = 4;
200
201   data->d_size =
202     /* orig_e_shoff */ sizeof (Elf32_Off) +
203     /* n_sections */ sizeof (Elf32_Off) +
204     /* sections */ info->n_sections * sizeof (UnstripInfoSection32);
205
206   data->d_buf = calloc (1, data->d_size);
207
208   info32 = (UnstripInfo32 *) data->d_buf;
209
210   info32->orig_e_shoff = off32_to_file (info->orig_e_shoff, elf);
211   info32->n_sections = off32_to_file (info->n_sections, elf);
212
213   for (i = 0; i < info->n_sections; i++)
214     {
215       info32->sections[i].debug_section = word32_to_file (info->sections[i].debug_section, elf);
216       info32->sections[i].name = word32_to_file (info->sections[i].name, elf);
217       info32->sections[i].orig_offset = off32_to_file (info->sections[i].orig_offset, elf);
218     }
219 }
220
221 static void
222 unstrip_info_to_data64 (UnstripInfo *info,
223                         Elf *elf,
224                         Elf_Data *data)
225 {
226   UnstripInfo64 *info64;
227   int i;
228   
229   data->d_align = 8;
230   
231   data->d_size =
232     /* orig_e_shoff */ sizeof (Elf64_Off) +
233     /* n_sections */ sizeof (Elf64_Off) +
234     /* sections */ info->n_sections * sizeof (UnstripInfoSection64);
235
236   data->d_buf = calloc (1, data->d_size);
237
238   info64 = (UnstripInfo64 *) data->d_buf;
239
240   info64->orig_e_shoff = off64_to_file (info->orig_e_shoff, elf);
241   info64->n_sections = off64_to_file (info->n_sections, elf);
242
243   for (i = 0; i < info->n_sections; i++)
244     {
245       info64->sections[i].debug_section = word64_to_file (info->sections[i].debug_section, elf);
246       info64->sections[i].name = word64_to_file (info->sections[i].name, elf);
247       info64->sections[i].orig_offset = off64_to_file (info->sections[i].orig_offset, elf);
248     }
249 }
250
251 void
252 unstrip_info_to_data (UnstripInfo *info,
253                       Elf *elf,
254                       Elf_Data *data)
255 {
256   GElf_Ehdr ehdr;
257   
258   data->d_type = ELF_T_BYTE;
259   data->d_off = 0;
260
261   gelf_getehdr (elf, &ehdr);
262   if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
263     unstrip_info_to_data32 (info, elf, data);
264   else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
265     unstrip_info_to_data64 (info, elf, data);
266   else
267     fprintf (stderr, "Warning. unsupported elf class\n");
268 }
269
270 static void
271 unstrip_info_from_data32 (UnstripInfo *info,
272                           Elf *elf,
273                           Elf_Data *data)
274 {
275   UnstripInfo32 *info32;
276   int i;
277   
278   info32 = (UnstripInfo32 *) data->d_buf;
279   
280   info->orig_e_shoff = off32_from_file (info32->orig_e_shoff, elf);
281   info->n_sections = off32_from_file (info32->n_sections, elf);
282
283   info->sections = calloc (info->n_sections, sizeof (UnstripInfoSection));
284   for (i = 0; i < info->n_sections; i++)
285     {
286       info->sections[i].debug_section = word32_from_file (info32->sections[i].debug_section, elf);
287       info->sections[i].name = word32_from_file (info32->sections[i].name, elf);
288       info->sections[i].orig_offset = off32_from_file (info32->sections[i].orig_offset, elf);
289     }
290 }
291
292 static void
293 unstrip_info_from_data64 (UnstripInfo *info,
294                           Elf *elf,
295                           Elf_Data *data)
296 {
297   UnstripInfo64 *info64;
298   int i;
299   
300   info64 = (UnstripInfo64 *) data->d_buf;
301   
302   info->orig_e_shoff = off64_from_file (info64->orig_e_shoff, elf);
303   info->n_sections = off64_from_file (info64->n_sections, elf);
304
305   info->sections = calloc (info->n_sections, sizeof (UnstripInfoSection));
306   for (i = 0; i < info->n_sections; i++)
307     {
308       info->sections[i].debug_section = word64_from_file (info64->sections[i].debug_section, elf);
309       info->sections[i].name = word64_from_file (info64->sections[i].name, elf);
310       info->sections[i].orig_offset = off64_from_file (info64->sections[i].orig_offset, elf);
311     }
312 }
313
314 UnstripInfo *
315 unstrip_info_from_data (Elf *elf,
316                         Elf_Data *data)
317 {
318   GElf_Ehdr ehdr;
319   
320   UnstripInfo *info;
321
322   info = malloc (sizeof (UnstripInfo));
323
324   gelf_getehdr (elf, &ehdr);
325   if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
326     unstrip_info_from_data32 (info, elf, data);
327   else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
328     unstrip_info_from_data64 (info, elf, data);
329   else
330     fprintf (stderr, "Warning. unsupported elf class\n");
331   
332   return info;
333 }
334
335 static void
336 debug_link_to_data32 (DebugLink *debuglink,
337                       Elf *elf,
338                       Elf_Data *data)
339 {
340   size_t namelen_aligned;
341   char *p;
342   
343   data->d_align = 4;
344
345   namelen_aligned = align_up (strlen(debuglink->filename) + 1, 4);
346
347   data->d_size =
348     /* name */ namelen_aligned +
349     /* checksum */ sizeof (Elf32_Word);
350
351   data->d_buf = calloc (1, data->d_size);
352
353   strcpy (data->d_buf, debuglink->filename);
354   p = ((char *)data->d_buf) + namelen_aligned;
355   
356   *(Elf32_Word *)p = word32_to_file (debuglink->checksum, elf);
357 }
358
359 static void
360 debug_link_to_data64 (DebugLink *debuglink,
361                       Elf *elf,
362                       Elf_Data *data)
363 {
364   size_t namelen_aligned;
365   char *p;
366   
367   data->d_align = 4;
368
369   namelen_aligned = align_up (strlen(debuglink->filename) + 1, 4);
370
371   data->d_size =
372     /* name */ namelen_aligned +
373     /* checksum */ sizeof (Elf64_Word);
374
375   data->d_buf = calloc (1, data->d_size);
376
377   strcpy (data->d_buf, debuglink->filename);
378   p = ((char *)data->d_buf) + namelen_aligned;
379   
380   *(Elf64_Word *)p = word64_to_file (debuglink->checksum, elf);
381 }
382
383 void
384 debug_link_to_data (DebugLink *debuglink, Elf *elf, Elf_Data *data)
385 {
386   GElf_Ehdr ehdr;
387   
388   data->d_type = ELF_T_BYTE;
389   data->d_off = 0;
390
391   gelf_getehdr (elf, &ehdr);
392   if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
393     debug_link_to_data32 (debuglink, elf, data);
394   else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
395     debug_link_to_data64 (debuglink, elf, data);
396   else
397     fprintf (stderr, "Warning. unsupported elf class\n");
398 }
399
400 static void
401 debug_link_from_data32 (DebugLink *debuglink,
402                         Elf *elf,
403                         Elf_Data *data)
404 {
405   size_t namelen_aligned;
406   char *p;
407   
408   debuglink->filename = strdup (data->d_buf);
409
410   namelen_aligned = align_up (strlen (debuglink->filename) + 1, 4);
411
412   p = ((char *)data->d_buf) + namelen_aligned;
413   
414   debuglink->checksum = word32_from_file (*(Elf32_Word *)p, elf);
415 }
416
417 static void
418 debug_link_from_data64 (DebugLink *debuglink,
419                         Elf *elf,
420                         Elf_Data *data)
421 {
422   size_t namelen_aligned;
423   char *p;
424   
425   debuglink->filename = strdup (data->d_buf);
426
427   namelen_aligned = align_up (strlen (debuglink->filename) + 1, 4);
428
429   p = ((char *)data->d_buf) + namelen_aligned;
430   
431   debuglink->checksum = word64_from_file (*(Elf64_Word *)p, elf);
432 }
433
434
435 DebugLink *
436 debug_link_from_data (Elf *elf, Elf_Data *data)
437 {
438   GElf_Ehdr ehdr;
439   DebugLink *debuglink;
440
441   debuglink = malloc (sizeof (DebugLink));
442
443   gelf_getehdr (elf, &ehdr);
444   if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
445     debug_link_from_data32 (debuglink, elf, data);
446   else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
447     debug_link_from_data64 (debuglink, elf, data);
448   else
449     fprintf (stderr, "Warning. unsupported elf class\n");
450   
451   return debuglink;
452 }
453