comparison src/os/solaris/add_gnu_debuglink/add_gnu_debuglink.c @ 6077:7d4e6dabc6bf

7165060: dtrace tests fail with FDS debug info files Summary: Work around 'gobjcopy --add-gnu-debuglink' failure by adding a temporary tool that adds the '.gnu_debuglink' section and nothing more. Reviewed-by: sspitsyn, acorn
author dcubed
date Tue, 15 May 2012 10:52:24 -0700
parents
children
comparison
equal deleted inserted replaced
6021:744728c16316 6077:7d4e6dabc6bf
1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 /*
26 * Name: add_gnu_debuglink.c
27 *
28 * Description: Add a ".gnu_debuglink" section that refers to the specified
29 * debug_info_path to the specified ELF object.
30 *
31 * This program is adapted from the example program shown on the
32 * elf(3elf) man page and from code from the Solaris compiler
33 * driver.
34 */
35
36 /*
37 * needed to define SHF_EXCLUDE
38 */
39 #define ELF_TARGET_ALL
40
41 #include <fcntl.h>
42 #include <stdio.h>
43 #include <libelf.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 static void failure(void);
49 static unsigned int gnu_debuglink_crc32(unsigned int crc, unsigned char *buf,
50 size_t len);
51
52 void
53 main(int argc, char ** argv) {
54 /* new ELF section name */
55 static char SEC_NAME[] = ".gnu_debuglink";
56
57 unsigned char buffer[8 * 1024]; /* I/O buffer */
58 int buffer_len; /* buffer length */
59 char * debug_info_path; /* debug info path */
60 void * ehdr; /* ELF header */
61 Elf * elf; /* ELF descriptor */
62 char * elf_ident; /* ELF identity string */
63 char * elf_obj; /* elf_obj file */
64 int fd; /* descriptor for files */
65 unsigned int file_crc = 0; /* CRC for debug info file */
66 int is_elfclass64; /* is an ELFCLASS64 file? */
67 Elf_Data * link_dat; /* ELF data for new debug info link */
68 Elf_Data * name_dat; /* ELF data for new section name */
69 Elf_Scn * new_scn; /* new ELF section descriptor */
70 void * new_shdr; /* new ELF section header */
71 Elf_Scn * scn; /* ELF section descriptor */
72 void * shdr; /* ELF section header */
73
74 if (argc != 3) {
75 (void) fprintf(stderr, "Usage: %s debug_info_path elf_obj\n", argv[0]);
76 exit(2);
77 }
78
79 debug_info_path = argv[1]; /* save for later */
80 if ((fd = open(debug_info_path, O_RDONLY)) == -1) {
81 (void) fprintf(stderr, "%s: cannot open file.\n", debug_info_path);
82 exit(3);
83 }
84
85 (void) printf("Computing CRC for '%s'\n", debug_info_path);
86 (void) fflush(stdout);
87 /* compute CRC for the debug info file */
88 for (;;) {
89 int len = read(fd, buffer, sizeof buffer);
90 if (len <= 0) {
91 break;
92 }
93 file_crc = gnu_debuglink_crc32(file_crc, buffer, len);
94 }
95 (void) close(fd);
96
97 /* open the elf_obj */
98 elf_obj = argv[2];
99 if ((fd = open(elf_obj, O_RDWR)) == -1) {
100 (void) fprintf(stderr, "%s: cannot open file.\n", elf_obj);
101 exit(4);
102 }
103
104 (void) printf("Opening '%s' for update\n", elf_obj);
105 (void) fflush(stdout);
106 (void) elf_version(EV_CURRENT); /* coordinate ELF versions */
107
108 /* obtain the ELF descriptors from the input file */
109 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
110 failure();
111 }
112
113 /* determine if ELFCLASS64 or not? */
114 elf_ident = elf_getident(elf, NULL);
115 is_elfclass64 = (elf_ident[EI_CLASS] == ELFCLASS64);
116
117 /* get the ELF header */
118 if (is_elfclass64) {
119 ehdr = elf64_getehdr(elf);
120 } else {
121 ehdr = elf32_getehdr(elf);
122 }
123 if (ehdr == NULL) {
124 failure();
125 }
126
127 /* get the ELF section descriptor */
128 if (is_elfclass64) {
129 scn = elf_getscn(elf, ((Elf64_Ehdr *) ehdr)->e_shstrndx);
130 } else {
131 scn = elf_getscn(elf, ((Elf32_Ehdr *) ehdr)->e_shstrndx);
132 }
133 if (scn == NULL) {
134 failure();
135 }
136
137 /* get the section header */
138 if (is_elfclass64) {
139 shdr = elf64_getshdr(scn);
140 } else {
141 shdr = elf32_getshdr(scn);
142 }
143 if (shdr == NULL) {
144 failure();
145 }
146
147 (void) printf("Adding ELF data for new section name\n");
148 (void) fflush(stdout);
149 name_dat = elf_newdata(scn);
150 name_dat->d_buf = (void *) SEC_NAME;
151 if (is_elfclass64) {
152 name_dat->d_off = ((Elf64_Shdr *) shdr)->sh_size + 1;
153 } else {
154 name_dat->d_off = ((Elf32_Shdr *) shdr)->sh_size + 1;
155 }
156 name_dat->d_align = 1;
157 name_dat->d_size = strlen(SEC_NAME) + 1;
158
159 new_scn = elf_newscn(elf);
160
161 if (is_elfclass64) {
162 new_shdr = elf64_getshdr(new_scn);
163 ((Elf64_Shdr *) new_shdr)->sh_flags = SHF_EXCLUDE;
164 ((Elf64_Shdr *) new_shdr)->sh_type = SHT_PROGBITS;
165 ((Elf64_Shdr *) new_shdr)->sh_name = ((Elf64_Shdr *) shdr)->sh_size;
166 ((Elf64_Shdr *) new_shdr)->sh_addralign = 1;
167 ((Elf64_Shdr *) shdr)->sh_size += (strlen(SEC_NAME) + 1);
168 } else {
169 new_shdr = elf32_getshdr(new_scn);
170 ((Elf32_Shdr *) new_shdr)->sh_flags = SHF_EXCLUDE;
171 ((Elf32_Shdr *) new_shdr)->sh_type = SHT_PROGBITS;
172 ((Elf32_Shdr *) new_shdr)->sh_name = ((Elf32_Shdr *) shdr)->sh_size;
173 ((Elf32_Shdr *) new_shdr)->sh_addralign = 1;
174 ((Elf32_Shdr *) shdr)->sh_size += (strlen(SEC_NAME) + 1);
175 }
176
177 (void) printf("Adding ELF data for debug_info_path value\n");
178 (void) fflush(stdout);
179 (void) memset(buffer, 0, sizeof buffer);
180 buffer_len = strlen(debug_info_path) + 1; /* +1 for NUL */
181 (void) strncpy((char *) buffer, debug_info_path, buffer_len);
182 if (buffer_len % 4 != 0) {
183 /* not on a 4 byte boundary so pad to the next one */
184 buffer_len += (4 - buffer_len % 4);
185 }
186 /* save the CRC */
187 (void) memcpy(&buffer[buffer_len], &file_crc, sizeof file_crc);
188 buffer_len += sizeof file_crc;
189
190 link_dat = elf_newdata(new_scn);
191 link_dat->d_type = ELF_T_BYTE;
192 link_dat->d_size = buffer_len;
193 link_dat->d_buf = buffer;
194 link_dat->d_align = 1;
195
196 (void) printf("Saving updates to '%s'\n", elf_obj);
197 (void) fflush(stdout);
198 (void) elf_update(elf, ELF_C_NULL); /* recalc ELF memory structures */
199 (void) elf_update(elf, ELF_C_WRITE); /* write out changes to ELF obj */
200 (void) elf_end(elf); /* done with ELF obj */
201 (void) close(fd);
202
203 (void) printf("Done updating '%s'\n", elf_obj);
204 (void) fflush(stdout);
205 exit(0);
206 } /* end main */
207
208
209 static void
210 failure() {
211 (void) fprintf(stderr, "%s\n", elf_errmsg(elf_errno()));
212 exit(5);
213 }
214
215
216 /*
217 * The CRC used in gnu_debuglink, retrieved from
218 * http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files.
219 */
220
221 static unsigned int
222 gnu_debuglink_crc32(unsigned int crc, unsigned char *buf, size_t len) {
223 static const unsigned int crc32_table[256] = {
224 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
225 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
226 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
227 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
228 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
229 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
230 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
231 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
232 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
233 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
234 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
235 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
236 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
237 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
238 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
239 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
240 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
241 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
242 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
243 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
244 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
245 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
246 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
247 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
248 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
249 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
250 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
251 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
252 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
253 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
254 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
255 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
256 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
257 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
258 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
259 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
260 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
261 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
262 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
263 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
264 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
265 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
266 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
267 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
268 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
269 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
270 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
271 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
272 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
273 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
274 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
275 0x2d02ef8d
276 };
277
278 unsigned char *end;
279
280 crc = ~crc & 0xffffffff;
281 for (end = buf + len; buf < end; ++buf) {
282 crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
283 }
284 return ~crc & 0xffffffff;
285 }