Print this page
4011 ar does weird things with extended ELF sections
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/ar/common/file.c
+++ new/usr/src/cmd/sgs/ar/common/file.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Copyright (c) 1988 AT&T
28 28 * All Rights Reserved
29 29 *
30 30 */
31 31
32 32 #include <sys/sendfile.h>
33 33 #include "inc.h"
34 34 #include "gelf.h"
35 35
36 36 /*
37 37 * List of archive members, accessed globally by cmd and file.
38 38 */
39 39 ARFILE *listhead, *listend;
40 40
41 41 /*
42 42 * Type used to manage string tables. Archives can have two of these:
43 43 *
44 44 * sym_strtbl: String table included at the end of the symbol table
45 45 * archive member, following the offset array.
46 46 *
47 47 * long_strtbl: String table used to hold member names that exceed 15
48 48 * characters in length, found in the long names archive member.
49 49 */
50 50 typedef struct {
51 51 char *base; /* Base of string table memory */
52 52 size_t used; /* # bytes used from allocation */
53 53 size_t size; /* Size of allocation */
54 54 } ARSTRTBL;
55 55
56 56 static ARSTRTBL sym_strtbl;
57 57 static ARSTRTBL long_strtbl;
58 58
59 59
60 60 /*
61 61 * Name and file descriptor used when creating a new archive.
62 62 * If this variable references an open file when exit_cleanup()
63 63 * executes, it will close and remove the file, preventing incomplete
64 64 * temporary files from being left behind in the case of a failure
65 65 * or interruption.
66 66 */
67 67 static struct {
68 68 int fd; /* -1, or open file descriptor */
69 69 const char *path; /* Path to open file */
70 70 } ar_outfile;
71 71
72 72 /*
73 73 * The ar file format requires objects to be padded to an even size.
74 74 * We do that, but it turns out to be beneficial to go farther.
75 75 *
76 76 * ld(1) accesses archives by mmapping them into memory. If the mapped
77 77 * objects (member data) have the proper alignment, we can access them
78 78 * directly. If the data alignment is wrong, libelf "slides" them over the
79 79 * archive header to correct the misalignment. This is expensive in time
80 80 * (to copy memory) and space (it causes swap to be allocated by the system
81 81 * to back the now-modified pages). Hence, we really want to ensure that
82 82 * the alignment is right.
83 83 *
84 84 * We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects
85 85 * at 8-byte. More recently, an elf section type has appeared that has
86 86 * 8-byte alignment requirements (SUNW_move) even in 32-bit objects. So,
87 87 * the current strategy is to align all objects to 8-bytes.
88 88 *
89 89 * There are two important things to consider when setting this value:
90 90 * 1) If a new elf section that ld(1) accesses in memory appears
91 91 * with a greater than 8-byte alignment requirement, this value
92 92 * will need to be raised. Or, alternatively, the entire approach may
93 93 * need reconsideration.
94 94 * 2) The size of this padding must be smaller than the size of the
95 95 * smallest possible ELF section. Otherwise, the logic contained
96 96 * in recover_padding() can be tricked.
97 97 */
98 98 #define PADSZ 8
99 99
100 100 /*
101 101 * Forward Declarations
102 102 */
103 103 static void arwrite(const char *, int, const char *, size_t);
104 104 static size_t mklong_tab();
105 105 static size_t mksymtab(const char *, ARFILEP **, int *);
106 106 static const char *make_tmpname(const char *);
107 107 static size_t sizeof_symtbl(size_t, int, size_t);
108 108 static void savelongname(ARFILE *);
109 109 static void savename(char *);
110 110 static int search_sym_tab(const char *, ARFILE *, Elf *,
111 111 Elf_Scn *, size_t *, ARFILEP **, size_t *);
112 112 static size_t sizeofmembers(size_t);
113 113 static char *sputl32(uint32_t, char *);
114 114 static char *sputl64(uint64_t, char *);
115 115 static void strtbl_pad(ARSTRTBL *, size_t, int);
116 116 static char *trimslash(char *s);
117 117 static void writesymtab(const char *, int fd, size_t, ARFILEP *,
118 118 size_t);
119 119
120 120
121 121 /*
122 122 * Function to be called on exit to clean up incomplete new archive.
123 123 */
124 124 static void
125 125 exit_cleanup(void)
126 126 {
127 127 if (ar_outfile.fd != -1) {
128 128 /* Both of these system calls are Async-Signal-Safe */
129 129 (void) close(ar_outfile.fd);
130 130 (void) unlink(ar_outfile.path);
131 131 }
132 132 }
133 133
134 134 /*
135 135 * Open an existing archive.
136 136 */
137 137 int
138 138 getaf(Cmd_info *cmd_info)
139 139 {
140 140 Elf_Cmd cmd;
141 141 int fd;
142 142 char *arnam = cmd_info->arnam;
143 143
144 144 if (elf_version(EV_CURRENT) == EV_NONE) {
145 145 (void) fprintf(stderr, MSG_INTL(MSG_ELF_VERSION),
146 146 elf_errmsg(-1));
147 147 exit(1);
148 148 }
149 149
150 150 if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) {
151 151 int err = errno;
152 152
153 153 if (err == ENOENT) {
154 154 /* archive does not exist yet, may have to create one */
155 155 return (fd);
156 156 } else {
157 157 /* problem other than "does not exist" */
158 158 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
159 159 arnam, strerror(err));
160 160 exit(1);
161 161 }
162 162 }
163 163
164 164 cmd = ELF_C_READ;
165 165 cmd_info->arf = elf_begin(fd, cmd, (Elf *)0);
166 166
167 167 if (elf_kind(cmd_info->arf) != ELF_K_AR) {
168 168 (void) fprintf(stderr, MSG_INTL(MSG_NOT_ARCHIVE), arnam);
169 169 if (cmd_info->opt_flgs & (a_FLAG | b_FLAG))
170 170 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_06),
171 171 cmd_info->ponam);
172 172 exit(1);
173 173 }
174 174 return (fd);
175 175 }
176 176
177 177 /*
178 178 * Given a value, and a pad alignment, return the number of bytes
179 179 * required to pad the value to the next alignment boundary.
180 180 */
181 181 static size_t
182 182 pad(size_t n, size_t align)
183 183 {
184 184 size_t r;
185 185
186 186 r = n % align;
187 187 if (r)
188 188 r = align - r;
189 189
190 190 return (r);
191 191 }
192 192
193 193 /*
194 194 * If the current archive item is an ELF object, then ar(1) may have added
195 195 * newline padding at the end in order to bring the following object
196 196 * into PADSZ alignment within the file. This padding cannot be
197 197 * distinguished from data using the information kept in the member header.
↓ open down ↓ |
197 lines elided |
↑ open up ↑ |
198 198 * This routine examines the objects, using knowledge of
199 199 * ELF and how our tools lay out objects to determine whether padding was
200 200 * added to an archive item. If so, it adjusts the st_size and
201 201 * st_padding fields of the file argument to reflect it.
202 202 */
203 203 static void
204 204 recover_padding(Elf *elf, ARFILE *file)
205 205 {
206 206 size_t extent;
207 207 size_t padding;
208 + size_t shnum;
208 209 GElf_Ehdr ehdr;
209 210
210 211
211 212 /* ar(1) only pads objects, so bail if not looking at one */
212 213 if (gelf_getclass(elf) == ELFCLASSNONE)
213 214 return;
214 215
215 216 /*
216 217 * libelf always puts the section header array at the end
217 218 * of the object, and all of our compilers and other tools
218 219 * use libelf or follow this convention. So, it is extremely
219 220 * likely that the section header array is at the end of this
220 221 * object: Find the address at the end of the array and compare
221 222 * it to the archive ar_size. If they are within PADSZ bytes, then
222 223 * we've found the end, and the difference is padding (We assume
223 224 * that no ELF section can fit into PADSZ bytes).
224 225 */
226 + if (elf_getshdrnum(elf, &shnum) == -1)
227 + return;
228 +
225 229 extent = gelf_getehdr(elf, &ehdr)
226 - ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0;
230 + ? (ehdr.e_shoff + (shnum * ehdr.e_shentsize)) : 0;
227 231
228 232 /*
229 233 * If the extent exceeds the end of the archive member
230 234 * (negative padding), then we don't know what is going on
231 235 * and simply leave things alone.
232 236 */
233 237 if (extent > file->ar_size)
234 238 return;
235 239
236 240 padding = file->ar_size - extent;
237 241 if (padding >= PADSZ) {
238 242 /*
239 243 * The section header array is not at the end of the object.
240 244 * Traverse the section headers and look for the one with
241 245 * the highest used address. If this address is within
242 246 * PADSZ bytes of ar_size, then this is the end of the object.
243 247 */
244 248 Elf_Scn *scn = NULL;
245 249
246 250 do {
247 251 scn = elf_nextscn(elf, scn);
248 252 if (scn) {
249 253 GElf_Shdr shdr;
250 254
251 255 if (gelf_getshdr(scn, &shdr)) {
252 256 size_t t;
253 257
254 258 t = shdr.sh_offset + shdr.sh_size;
255 259 if (t > extent)
256 260 extent = t;
257 261 }
258 262 }
259 263 } while (scn);
260 264
261 265 if (extent > file->ar_size)
262 266 return;
263 267 padding = file->ar_size - extent;
264 268 }
265 269
266 270 /*
267 271 * Now, test the padding. We only act on padding in the range
268 272 * (0 < pad < PADSZ) (ar(1) will never add more than this). A pad
269 273 * of 0 requires no action, and any other size above (PADSZ-1) means
270 274 * that we don't understand the layout of this object, and as such,
271 275 * cannot do anything.
272 276 *
273 277 * If the padding is in range, and the raw data for the
274 278 * object is available, then we perform one additional sanity
275 279 * check before moving forward: ar(1) always pads with newline
276 280 * characters. If anything else is seen, it is not padding so
277 281 * leave it alone.
278 282 */
279 283 if (padding < PADSZ) {
280 284 if (file->ar_contents) {
281 285 size_t cnt = padding;
282 286 char *p = file->ar_contents + extent;
283 287
284 288 while (cnt--) {
285 289 if (*p++ != '\n') { /* No padding */
286 290 padding = 0;
287 291 break;
288 292 }
289 293 }
290 294 }
291 295
292 296 /* Remove the padding from the size */
293 297 file->ar_size -= padding;
294 298 file->ar_padding = padding;
295 299 }
296 300 }
297 301
298 302 /*
299 303 * Each call to getfile() returns the next unread archive member
300 304 * from the archive opened by getaf(). Returns NULL if no more
301 305 * archive members are left.
302 306 */
303 307 ARFILE *
304 308 getfile(Cmd_info *cmd_info)
305 309 {
306 310 Elf_Arhdr *mem_header = NULL;
307 311 ARFILE *file;
308 312 char *tmp_rawname, *file_rawname;
309 313 Elf *elf;
310 314 char *arnam = cmd_info->arnam;
311 315 int fd = cmd_info->afd;
312 316 Elf *arf = cmd_info->arf;
313 317
314 318 if (fd == -1)
315 319 return (NULL); /* the archive doesn't exist */
316 320
317 321 while (mem_header == NULL) {
318 322 if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0)
319 323 return (NULL); /* archive is empty or have hit end */
320 324
321 325 if ((mem_header = elf_getarhdr(elf)) == NULL) {
322 326 (void) fprintf(stderr, MSG_INTL(MSG_ELF_MALARCHIVE),
323 327 arnam, EC_XWORD(elf_getbase(elf)), elf_errmsg(-1));
324 328 exit(1);
325 329 }
326 330
327 331 /* Ignore special members like the symbol and string tables */
328 332 if (mem_header->ar_name[0] == '/') {
329 333 (void) elf_next(elf);
330 334 (void) elf_end(elf);
331 335 mem_header = NULL;
332 336 }
333 337 }
334 338
335 339 /*
336 340 * NOTE:
337 341 * The mem_header->ar_name[] is set to a NULL string
338 342 * if the archive member header has some error.
339 343 * (See elf_getarhdr() man page.)
340 344 * It is set to NULL for example, the ar command reads
341 345 * the archive files created by SunOS 4.1 system.
342 346 * See c block comment in cmd.c, "Incompatible Archive Header".
343 347 */
344 348 file = newfile();
345 349 (void) strncpy(file->ar_name, mem_header->ar_name, SNAME);
346 350
347 351 if ((file->ar_longname = malloc(strlen(mem_header->ar_name) + 1))
348 352 == NULL) {
349 353 int err = errno;
350 354 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
351 355 exit(1);
352 356 }
353 357 (void) strcpy(file->ar_longname, mem_header->ar_name);
354 358 if ((file->ar_rawname = malloc(strlen(mem_header->ar_rawname) + 1))
355 359 == NULL) {
356 360 int err = errno;
357 361 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
358 362 exit(1);
359 363 }
360 364 tmp_rawname = mem_header->ar_rawname;
361 365 file_rawname = file->ar_rawname;
362 366 while (!isspace(*tmp_rawname) &&
363 367 ((*file_rawname = *tmp_rawname) != '\0')) {
364 368 file_rawname++;
365 369 tmp_rawname++;
366 370 }
367 371 if (!(*tmp_rawname == '\0'))
368 372 *file_rawname = '\0';
369 373
370 374 file->ar_date = mem_header->ar_date;
371 375 file->ar_uid = mem_header->ar_uid;
372 376 file->ar_gid = mem_header->ar_gid;
373 377 file->ar_mode = (unsigned long) mem_header->ar_mode;
374 378 file->ar_size = mem_header->ar_size;
375 379
376 380 /* reverse logic */
377 381 if ((cmd_info->opt_flgs & (t_FLAG | s_FLAG)) != t_FLAG) {
378 382 size_t ptr;
379 383 file->ar_flag = F_ELFRAW;
380 384 if ((file->ar_contents = elf_rawfile(elf, &ptr))
381 385 == NULL) {
382 386 if (ptr != 0) {
383 387 (void) fprintf(stderr,
384 388 MSG_INTL(MSG_ELF_RAWFILE), elf_errmsg(-1));
385 389 exit(1);
386 390 }
387 391 }
388 392 file->ar_elf = elf;
389 393 }
390 394
391 395 recover_padding(elf, file);
392 396
393 397 (void) elf_next(elf);
394 398 return (file);
395 399 }
396 400
397 401 /*
398 402 * Allocate a new archive member descriptor and add it to the list.
399 403 */
400 404 ARFILE *
401 405 newfile(void)
402 406 {
403 407 static ARFILE *buffer = NULL;
404 408 static size_t count = 0;
405 409 ARFILE *fileptr;
406 410
407 411 if (count == 0) {
408 412 if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE)))
409 413 == NULL) {
410 414 int err = errno;
411 415 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
412 416 strerror(err));
413 417 exit(1);
414 418 }
415 419 count = CHUNK;
416 420 }
417 421 count--;
418 422 fileptr = buffer++;
419 423
420 424 if (listhead)
421 425 listend->ar_next = fileptr;
422 426 else
423 427 listhead = fileptr;
424 428 listend = fileptr;
425 429 return (fileptr);
426 430 }
427 431
428 432 static char *
429 433 trimslash(char *s)
430 434 {
431 435 static char buf[SNAME];
432 436
433 437 (void) strncpy(buf, trim(s), SNAME - 2);
434 438 buf[SNAME - 2] = '\0';
435 439 return (strcat(buf, MSG_ORIG(MSG_STR_SLASH)));
436 440 }
437 441
438 442 char *
439 443 trim(char *s)
440 444 {
441 445 char *p1, *p2;
442 446
443 447 for (p1 = s; *p1; p1++)
444 448 ;
445 449 while (p1 > s) {
446 450 if (*--p1 != '/')
447 451 break;
448 452 *p1 = 0;
449 453 }
450 454 p2 = s;
451 455 for (p1 = s; *p1; p1++)
452 456 if (*p1 == '/')
453 457 p2 = p1 + 1;
454 458 return (p2);
455 459 }
456 460
457 461
458 462 /*
459 463 * Find all the global symbols exported by ELF archive members, and
460 464 * build a list associating each one with the archive member that
461 465 * provides it.
462 466 *
463 467 * exit:
464 468 * *symlist is set to the list of symbols. If any ELF object was
465 469 * found, *found_obj is set to TRUE (1). Returns the number of symbols
466 470 * located.
467 471 */
468 472 static size_t
469 473 mksymtab(const char *arname, ARFILEP **symlist, int *found_obj)
470 474 {
471 475 ARFILE *fptr;
472 476 size_t mem_offset = 0;
473 477 Elf *elf;
474 478 Elf_Scn *scn;
475 479 GElf_Ehdr ehdr;
476 480 int newfd;
477 481 size_t nsyms = 0;
478 482 int class = 0;
479 483 Elf_Data *data;
480 484 size_t num_errs = 0;
481 485
482 486 newfd = 0;
483 487 for (fptr = listhead; fptr; fptr = fptr->ar_next) {
484 488 /* determine if file is coming from the archive or not */
485 489 if ((fptr->ar_elf != NULL) && (fptr->ar_pathname == NULL)) {
486 490 /*
487 491 * I can use the saved elf descriptor.
488 492 */
489 493 elf = fptr->ar_elf;
490 494 } else if ((fptr->ar_elf == NULL) &&
491 495 (fptr->ar_pathname != NULL)) {
492 496 #ifdef _LP64
493 497 /*
494 498 * The archive member header ar_size field is 10
495 499 * decimal digits, sufficient to represent a 32-bit
496 500 * value, but not a 64-bit one. Hence, we reject
497 501 * attempts to insert a member larger than 4GB.
498 502 *
499 503 * One obvious way to extend the format without altering
500 504 * the ar_hdr struct is to use the same mechanism used
501 505 * for ar_name: Put the size string into the long name
502 506 * string table and write a string /xxx into ar_size,
503 507 * where xxx is the string table offset.
504 508 *
505 509 * At the time of this writing (June 2010), the largest
506 510 * relocatable objects are measured in 10s or 100s
507 511 * of megabytes, so we still have many years to go
508 512 * before this becomes limiting. By that time, it may
509 513 * turn out that a completely new archive format is
510 514 * a better solution, as the current format has many
511 515 * warts and inefficiencies. In the meantime, we
512 516 * won't burden the current implementation with support
513 517 * for a bandaid feature that will have little use.
514 518 */
515 519 if (fptr->ar_size > 0xffffffff) {
516 520 (void) fprintf(stderr,
517 521 MSG_INTL(MSG_ERR_MEMBER4G),
518 522 fptr->ar_pathname);
519 523 num_errs++;
520 524 continue;
521 525 }
522 526 #endif
523 527 if ((newfd =
524 528 open(fptr->ar_pathname, O_RDONLY)) == -1) {
525 529 int err = errno;
526 530 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
527 531 fptr->ar_pathname, strerror(err));
528 532 num_errs++;
529 533 continue;
530 534 }
531 535
532 536 if ((elf = elf_begin(newfd,
533 537 ELF_C_READ, (Elf *)0)) == 0) {
534 538 (void) fprintf(stderr,
535 539 MSG_INTL(MSG_ELF_BEGIN_FILE),
536 540 fptr->ar_pathname, elf_errmsg(-1));
537 541 (void) close(newfd);
538 542 newfd = 0;
539 543 num_errs++;
540 544 continue;
541 545 }
542 546 if (elf_kind(elf) == ELF_K_AR) {
543 547 if (newfd) {
544 548 (void) close(newfd);
↓ open down ↓ |
308 lines elided |
↑ open up ↑ |
545 549 newfd = 0;
546 550 }
547 551 (void) elf_end(elf);
548 552 continue;
549 553 }
550 554 } else {
551 555 (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01));
552 556 exit(1);
553 557 }
554 558 if (gelf_getehdr(elf, &ehdr) != 0) {
559 + size_t shstrndx = 0;
555 560 if ((class = gelf_getclass(elf)) == ELFCLASS64) {
556 561 fptr->ar_flag |= F_CLASS64;
557 562 } else if (class == ELFCLASS32)
558 563 fptr->ar_flag |= F_CLASS32;
559 - scn = elf_getscn(elf, ehdr.e_shstrndx);
564 +
565 + if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
566 + if (fptr->ar_pathname != NULL) {
567 + (void) fprintf(stderr,
568 + MSG_INTL(MSG_ELF_GETSHDRSTRNDX_FILE),
569 + fptr->ar_pathname, elf_errmsg(-1));
570 + } else {
571 + (void) fprintf(stderr,
572 + MSG_INTL(MSG_ELF_GETSHDRSTRNDX_AR),
573 + arname, fptr->ar_longname,
574 + elf_errmsg(-1));
575 + }
576 + num_errs++;
577 + if (newfd) {
578 + (void) close(newfd);
579 + newfd = 0;
580 + }
581 + (void) elf_end(elf);
582 + continue;
583 + }
584 +
585 + scn = elf_getscn(elf, shstrndx);
560 586 if (scn == NULL) {
561 587 if (fptr->ar_pathname != NULL)
562 588 (void) fprintf(stderr,
563 589 MSG_INTL(MSG_ELF_GETSCN_FILE),
564 590 fptr->ar_pathname, elf_errmsg(-1));
565 591 else
566 592 (void) fprintf(stderr,
567 593 MSG_INTL(MSG_ELF_GETSCN_AR),
568 594 arname, fptr->ar_longname,
569 595 elf_errmsg(-1));
570 596 num_errs++;
571 597 if (newfd) {
572 598 (void) close(newfd);
573 599 newfd = 0;
574 600 }
575 601 (void) elf_end(elf);
576 602 continue;
577 603 }
578 604
579 605 data = 0;
580 606 data = elf_getdata(scn, data);
581 607 if (data == NULL) {
582 608 if (fptr->ar_pathname != NULL)
583 609 (void) fprintf(stderr,
584 610 MSG_INTL(MSG_ELF_GETDATA_FILE),
585 611 fptr->ar_pathname, elf_errmsg(-1));
586 612 else
587 613 (void) fprintf(stderr,
588 614 MSG_INTL(MSG_ELF_GETDATA_AR),
589 615 arname, fptr->ar_longname,
590 616 elf_errmsg(-1));
591 617 num_errs++;
592 618 if (newfd) {
593 619 (void) close(newfd);
594 620 newfd = 0;
595 621 }
596 622 (void) elf_end(elf);
597 623 continue;
598 624 }
599 625 if (data->d_size == 0) {
600 626 if (fptr->ar_pathname != NULL)
601 627 (void) fprintf(stderr,
602 628 MSG_INTL(MSG_W_ELF_NODATA_FILE),
603 629 fptr->ar_pathname);
604 630 else
605 631 (void) fprintf(stderr,
606 632 MSG_INTL(MSG_W_ELF_NODATA_AR),
607 633 arname, fptr->ar_longname);
608 634 if (newfd) {
609 635 (void) close(newfd);
610 636 newfd = 0;
611 637 }
612 638 (void) elf_end(elf);
613 639 num_errs++;
614 640 continue;
615 641 }
616 642
617 643 /* loop through sections to find symbol table */
618 644 scn = 0;
619 645 while ((scn = elf_nextscn(elf, scn)) != 0) {
620 646 GElf_Shdr shdr;
621 647 if (gelf_getshdr(scn, &shdr) == NULL) {
622 648 /* BEGIN CSTYLED */
623 649 if (fptr->ar_pathname != NULL)
624 650 (void) fprintf(stderr,
625 651 MSG_INTL(MSG_ELF_GETDATA_FILE),
626 652 fptr->ar_pathname,
627 653 elf_errmsg(-1));
628 654 else
629 655 (void) fprintf(stderr,
630 656 MSG_INTL(MSG_ELF_GETDATA_AR),
631 657 arname, fptr->ar_longname,
632 658 elf_errmsg(-1));
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
633 659 /* END CSTYLED */
634 660 if (newfd) {
635 661 (void) close(newfd);
636 662 newfd = 0;
637 663 }
638 664 num_errs++;
639 665 (void) elf_end(elf);
640 666 continue;
641 667 }
642 668 *found_obj = 1;
643 - if (shdr.sh_type == SHT_SYMTAB)
669 + if (shdr.sh_type == SHT_SYMTAB) {
644 670 if (search_sym_tab(arname, fptr, elf,
645 671 scn, &nsyms, symlist,
646 672 &num_errs) == -1) {
647 673 if (newfd) {
648 674 (void) close(newfd);
649 675 newfd = 0;
650 676 }
651 677 continue;
652 678 }
679 + }
653 680 }
654 681 }
655 682 mem_offset += sizeof (struct ar_hdr) + fptr->ar_size;
656 683 if (fptr->ar_size & 01)
657 684 mem_offset++;
658 685 (void) elf_end(elf);
659 686 if (newfd) {
660 687 (void) close(newfd);
661 688 newfd = 0;
662 689 }
663 690 }
664 691 if (num_errs)
665 692 exit(1);
666 693
667 694 if (found_obj) {
668 695 if (nsyms == 0) {
669 696 /*
670 697 * It is possible, though rare, to have ELF objects
671 698 * that do not export any global symbols. Presumably
672 699 * such objects operate via their .init/.fini
673 700 * sections. In this case, we produce an empty
674 701 * symbol table, so that applications that rely
675 702 * on a successful call to elf_getarsym() to determine
676 703 * if ELF objects are present will succeed. To do this,
677 704 * we require a small empty symbol string table.
678 705 */
679 706 strtbl_pad(&sym_strtbl, 4, '\0');
680 707 } else {
681 708 /*
682 709 * Historical behavior is to pad string tables
683 710 * to a multiple of 4.
684 711 */
685 712 strtbl_pad(&sym_strtbl, pad(sym_strtbl.used, 4), '\0');
686 713 }
687 714
688 715 }
689 716
690 717 return (nsyms);
691 718 }
692 719
693 720 /*
694 721 * Output a member header.
695 722 */
696 723 /*ARGSUSED*/
697 724 static void
698 725 write_member_header(const char *filename, int fd, int is_elf,
699 726 const char *name, time_t timestamp, uid_t uid, gid_t gid, mode_t mode,
700 727 size_t size)
701 728 {
702 729 char buf[sizeof (struct ar_hdr) + 1];
703 730 int len;
704 731
705 732 len = snprintf(buf, sizeof (buf), MSG_ORIG(MSG_MH_FORMAT), name,
706 733 EC_WORD(timestamp), EC_WORD(uid), EC_WORD(gid), EC_WORD(mode),
707 734 EC_XWORD(size), ARFMAG);
708 735
709 736 /*
710 737 * If snprintf() reports that it needed more space than we gave
711 738 * it, it means that the caller fed us a long name, which is a
712 739 * fatal internal error.
713 740 */
714 741 if (len != sizeof (struct ar_hdr)) {
715 742 (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_02));
716 743 exit(1);
717 744 }
718 745
719 746 arwrite(filename, fd, buf, len);
720 747
721 748 /*
722 749 * We inject inter-member padding to ensure that ELF object
723 750 * member data is aligned on PADSZ. If this is a debug build,
724 751 * verify that the computations were right.
725 752 */
726 753 assert(!is_elf || (pad(lseek(fd, 0, SEEK_CUR), PADSZ) == 0));
727 754 }
728 755
729 756 /*
730 757 * Write the archive symbol table member to the output archive file.
731 758 *
732 759 * note:
733 760 * sizeofmembers() must have been called to establish member offset
734 761 * and padding values before writesymtab() is used.
735 762 */
736 763 static void
737 764 writesymtab(const char *filename, int fd, size_t nsyms, ARFILEP *symlist,
738 765 size_t eltsize)
739 766 {
740 767 size_t i, j;
741 768 ARFILEP *ptr;
742 769 size_t tblsize;
743 770 char *buf, *dst;
744 771 int is64 = (eltsize == 8);
745 772
746 773 /*
747 774 * We require a buffer large enough to hold a symbol table count,
748 775 * plus one offset for each symbol.
749 776 */
750 777 tblsize = (nsyms + 1) * eltsize;
751 778 if ((buf = dst = malloc(tblsize)) == NULL) {
752 779 int err = errno;
753 780 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
754 781 exit(1);
755 782 }
756 783
757 784 write_member_header(filename, fd, 0,
758 785 (is64 ? MSG_ORIG(MSG_STR_SYM64) : MSG_ORIG(MSG_STR_SLASH)),
759 786 time(0), 0, 0, 0, tblsize + sym_strtbl.used);
760 787
761 788 dst = is64 ? sputl64(nsyms, dst) : sputl32(nsyms, dst);
762 789
763 790 for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) {
764 791 if (!j) {
765 792 j = SYMCHUNK;
766 793 ptr = (ARFILEP *)*ptr;
767 794 }
768 795 dst = is64 ? sputl64((*ptr)->ar_offset, dst) :
769 796 sputl32((*ptr)->ar_offset, dst);
770 797 }
771 798 arwrite(filename, fd, buf, tblsize);
772 799 free(buf);
773 800 arwrite(filename, fd, sym_strtbl.base, sym_strtbl.used);
774 801 }
775 802
776 803 /*
777 804 * Grow the size of the given string table so that there is room
778 805 * for at least need bytes.
779 806 *
780 807 * entry:
781 808 * strtbl - String table to grow
782 809 * need - Amount of space required by caller
783 810 */
784 811 static void
785 812 strtbl_alloc(ARSTRTBL *strtbl, size_t need)
786 813 {
787 814 #define STRTBL_INITSZ 8196
788 815
789 816 /*
790 817 * On 32-bit systems, we require a larger integer type in order
791 818 * to avoid overflow and wraparound when doing our computations.
792 819 */
793 820 uint64_t need64 = need;
794 821 uint64_t used64 = strtbl->used;
795 822 uint64_t size64 = strtbl->size;
796 823 uint64_t target = need64 + used64;
797 824
798 825 int sys32, tbl32;
799 826
800 827 if (target <= size64)
801 828 return;
802 829
803 830 /*
804 831 * Detect 32-bit system. We might usually do this with the preprocessor,
805 832 * but it can serve as a predicate in tests that also apply to 64-bit
806 833 * systems.
807 834 */
808 835 sys32 = (sizeof (size_t) == 4);
809 836
810 837 /*
811 838 * The symbol string table can be larger than 32-bits on a 64-bit
812 839 * system. However, the long name table must stay below that limit.
813 840 * The reason for this is that there is not enough room in the ar_name
814 841 * field of the member header to represent 64-bit offsets.
815 842 */
816 843 tbl32 = (strtbl == &long_strtbl);
817 844
818 845 /*
819 846 * If request is larger than 4GB and we can't do it because we
820 847 * are a 32-bit program, or because the table is format limited,
821 848 * we can go no further.
822 849 */
823 850 if ((target > 0xffffffff) && (sys32 || tbl32))
824 851 goto limit_fail;
825 852
826 853 /* Default starting size */
827 854 if (strtbl->base == NULL)
828 855 size64 = STRTBL_INITSZ;
829 856
830 857 /*
831 858 * Our strategy is to double the size until we find a size that
832 859 * exceeds the request. However, if this table cannot exceed 4GB,
833 860 * then once we exceed 2GB, we switch to a strategy of taking the
834 861 * current request and rounding it up to STRTBL_INITSZ.
835 862 */
836 863 while (target > size64) {
837 864 if ((target > 0x7fffffff) && (sys32 || tbl32)) {
838 865 size64 = ((target + STRTBL_INITSZ) / STRTBL_INITSZ) *
839 866 STRTBL_INITSZ;
840 867
841 868 /*
842 869 * If we are so close to the line that this small
843 870 * increment exceeds 4GB, give it up.
844 871 */
845 872 if ((size64 > 0xffffffff) && (sys32 || tbl32))
846 873 goto limit_fail;
847 874
848 875 break;
849 876 }
850 877
851 878 size64 *= 2;
852 879 }
853 880
854 881 strtbl->base = realloc(strtbl->base, size64);
855 882 if (strtbl->base == NULL) {
856 883 int err = errno;
857 884 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
858 885 exit(1);
859 886 }
860 887 strtbl->size = (size_t)size64;
861 888 return;
862 889
863 890 limit_fail:
864 891 /*
865 892 * Control comes here if we are unable to allocate more than 4GB of
866 893 * memory for the string table due to one of the following reasons:
867 894 *
868 895 * - A 32-bit process is attempting to be larger than 4GB
869 896 *
870 897 * - A 64-bit process is attempting to grow the long names string
871 898 * table beyond the ar format limit of 32-bits.
872 899 */
873 900 if (sys32)
874 901 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
875 902 else
876 903 (void) fprintf(stderr, MSG_INTL(MSG_ERR_LONGSTRTBLSZ));
877 904 exit(1);
878 905
879 906 #undef STRTBL_INITSZ
880 907 }
881 908
882 909 /*
883 910 * Add the specified number of pad characters to the end of the
884 911 * given string table.
885 912 *
886 913 * entry:
887 914 * strtbl - String table to pad
888 915 * n - # of pad characters to add
889 916 * ch - Pad character to use
890 917 */
891 918 static void
892 919 strtbl_pad(ARSTRTBL *strtbl, size_t n, int ch)
893 920 {
894 921 if (n == 0)
895 922 return;
896 923
897 924 if ((n + strtbl->used) > strtbl->size)
898 925 strtbl_alloc(strtbl, n);
899 926
900 927 while (n--)
901 928 strtbl->base[strtbl->used++] = ch;
902 929 }
903 930
904 931 /*
905 932 * Enter a symbol name into the symbol string table.
906 933 */
907 934 static void
908 935 savename(char *symbol)
909 936 {
910 937 size_t need;
911 938
912 939 need = strlen(symbol) + 1;
913 940 if ((need + sym_strtbl.used) > sym_strtbl.size)
914 941 strtbl_alloc(&sym_strtbl, need);
915 942
916 943 (void) strcpy(sym_strtbl.base + sym_strtbl.used, symbol);
917 944 sym_strtbl.used += need;
918 945 }
919 946
920 947 /*
921 948 * Prepare an archive member with a long (>15 characters) name for
922 949 * the output archive.
923 950 *
924 951 * entry:
925 952 * fptr - pointer to archive member with long name
926 953 *
927 954 * exit:
928 955 * The long name is entered into the long name string table,
929 956 * and fptr->ar_name has been replaced with the special /xxx
930 957 * name used to indicate that the real name is in the string table
931 958 * at offset xxx.
932 959 */
933 960 static void
934 961 savelongname(ARFILE *fptr)
935 962 {
936 963 size_t len, need;
937 964 char *p;
938 965
939 966 /* Size of new item to add */
940 967 len = strlen(fptr->ar_longname);
941 968 need = len + 2;
942 969
943 970 /* Ensure there's room */
944 971 if ((need + long_strtbl.used) > long_strtbl.size)
945 972 strtbl_alloc(&long_strtbl, need);
946 973
947 974 /*
948 975 * Generate the index string to be written into the member header
949 976 *
950 977 * This will not overflow the ar_name field because that field is
951 978 * 16 characters in size, and a 32-bit unsigned value can be formatted
952 979 * in 10 characters. Allowing a character for the leading '/', and one
953 980 * for the NULL termination, that leaves us with 4 extra spaces.
954 981 */
955 982 (void) snprintf(fptr->ar_name, sizeof (fptr->ar_name),
956 983 MSG_ORIG(MSG_FMT_LLINT), EC_XWORD(long_strtbl.used));
957 984
958 985 /*
959 986 * Enter long name into reserved spot, terminated with a slash
960 987 * and a newline character.
961 988 */
962 989 p = long_strtbl.base + long_strtbl.used;
963 990 long_strtbl.used += need;
964 991 (void) strcpy(p, fptr->ar_longname);
965 992 p += len;
966 993 *p++ = '/';
967 994 *p++ = '\n';
968 995 }
969 996
970 997 /*
971 998 * Determine if the archive we're about to write will exceed the
972 999 * 32-bit limit of 4GB.
973 1000 *
974 1001 * entry:
975 1002 * mksymtab() and mklong_tab() have been called to set up
976 1003 * the string tables.
977 1004 *
978 1005 * exit:
979 1006 * Returns TRUE (1) if the 64-bit symbol table is needed, and
980 1007 * FALSE (0) otherwise.
981 1008 *
982 1009 */
983 1010 static int
984 1011 require64(size_t nsyms, int found_obj, size_t longnames)
985 1012 {
986 1013 ARFILE *fptr;
987 1014 uint64_t size;
988 1015
989 1016 /*
990 1017 * If there are more than 4GB symbols, we have to use
991 1018 * the 64-bit form. Note that longnames cannot exceed 4GB
992 1019 * because that symbol table is limited to a length of 4GB by
993 1020 * the archive format.
994 1021 */
995 1022 if (nsyms > 0xffffffff)
996 1023 return (1);
997 1024
998 1025 /*
999 1026 * Make a worst case estimate for the size of the resulting
1000 1027 * archive by assuming full padding between members.
1001 1028 */
1002 1029 size = SARMAG;
1003 1030 if (longnames)
1004 1031 size += sizeof (struct ar_hdr) + long_strtbl.used + PADSZ;
1005 1032
1006 1033 if (found_obj)
1007 1034 size += sizeof_symtbl(nsyms, found_obj, 4) + PADSZ;
1008 1035
1009 1036 if (size > 0xffffffff)
1010 1037 return (1);
1011 1038
1012 1039 for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1013 1040 size += sizeof (struct ar_hdr) + fptr->ar_size + PADSZ;
1014 1041
1015 1042 if (size > 0xffffffff)
1016 1043 return (1);
1017 1044 }
1018 1045
1019 1046 /* 32-bit symbol table will suffice */
1020 1047 return (0);
1021 1048 }
1022 1049
1023 1050 void
1024 1051 writefile(Cmd_info *cmd_info)
1025 1052 {
1026 1053 ARFILE *fptr;
1027 1054 ARFILEP *symlist = 0;
1028 1055 size_t longnames;
1029 1056 size_t nsyms;
1030 1057 int new_archive = 0;
1031 1058 char *name = cmd_info->arnam;
1032 1059 size_t arsize; /* Size of magic # and special members */
1033 1060 size_t symtbl_eltsize = 4;
1034 1061 int found_obj = 0;
1035 1062 int fd;
1036 1063 off_t off;
1037 1064 struct stat stbuf, ar_stbuf;
1038 1065 char pad_bytes[PADSZ];
1039 1066 size_t pad_cnt;
1040 1067 int is_elf;
1041 1068
1042 1069 /*
1043 1070 * Gather the list of symbols and associate each one to the
1044 1071 * ARFILE descriptor of the object it belongs to. At the same
1045 1072 * time, tag each ELF object with the appropriate F_CLASSxx
1046 1073 * flag.
1047 1074 */
1048 1075 nsyms = mksymtab(name, &symlist, &found_obj);
1049 1076
1050 1077 /* Generate the string table for long member names */
1051 1078 longnames = mklong_tab();
1052 1079
1053 1080 /*
1054 1081 * Will this archive exceed 4GB? If we're a 32-bit process, we can't
1055 1082 * do it. If we're a 64-bit process, then we'll have to use a
1056 1083 * 64-bit symbol table.
1057 1084 */
1058 1085 if (require64(nsyms, found_obj, longnames)) {
1059 1086 #ifdef _LP64
1060 1087 symtbl_eltsize = 8;
1061 1088 #else
1062 1089 (void) fprintf(stderr, MSG_INTL(MSG_TOOBIG4G));
1063 1090 exit(1);
1064 1091 #endif
1065 1092 }
1066 1093
1067 1094 /*
1068 1095 * If the user requested it, use the 64-bit symbol table even if
1069 1096 * a 32-bit one would suffice. 32-bit tables are more portable and
1070 1097 * take up less room, so this feature is primarily for testing.
1071 1098 */
1072 1099 if (cmd_info->opt_flgs & S_FLAG)
1073 1100 symtbl_eltsize = 8;
1074 1101
1075 1102 /*
1076 1103 * If the first non-special archive member is an ELF object, then we
1077 1104 * need to arrange for its data to have an alignment of PADSZ. The
1078 1105 * preceeding special member will be the symbol table, or the long
1079 1106 * name string table. We pad the string table that precedes the
1080 1107 * ELF member in order to achive the desired alignment.
1081 1108 */
1082 1109 is_elf = listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64));
1083 1110 arsize = SARMAG;
1084 1111 if (found_obj) {
1085 1112 arsize += sizeof_symtbl(nsyms, found_obj, symtbl_eltsize);
1086 1113 if (is_elf && (longnames == 0)) {
1087 1114 pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
1088 1115 strtbl_pad(&sym_strtbl, pad_cnt, '\0');
1089 1116 arsize += pad_cnt;
1090 1117 }
1091 1118 }
1092 1119 if (longnames > 0) {
1093 1120 arsize += sizeof (struct ar_hdr) + long_strtbl.used;
1094 1121 if (is_elf) {
1095 1122 pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
1096 1123 strtbl_pad(&long_strtbl, pad_cnt, '\0');
1097 1124 arsize += pad_cnt;
1098 1125 }
1099 1126 }
1100 1127
1101 1128 /*
1102 1129 * For each user visible (non-special) archive member, determine
1103 1130 * the header offset, and the size of any required padding.
1104 1131 */
1105 1132 (void) sizeofmembers(arsize);
1106 1133
1107 1134 /*
1108 1135 * Is this a new archive, or are we updating an existing one?
1109 1136 *
1110 1137 * A subtlety here is that POSIX says we are not supposed
1111 1138 * to replace a non-writable file. The only 100% reliable test
1112 1139 * against this is to open the file for non-destructive
1113 1140 * write access. If the open succeeds, we are clear to
1114 1141 * replace it, and if not, then the error generated is
1115 1142 * the error we need to report.
1116 1143 */
1117 1144 if ((fd = open(name, O_RDWR)) < 0) {
1118 1145 int err = errno;
1119 1146
1120 1147 if (err != ENOENT) {
1121 1148 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1122 1149 name, strerror(err));
1123 1150 exit(1);
1124 1151 }
1125 1152 new_archive = 1;
1126 1153 if ((cmd_info->opt_flgs & c_FLAG) == 0) {
1127 1154 (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_CREATE),
1128 1155 cmd_info->arnam);
1129 1156 }
1130 1157 } else {
1131 1158 /* Capture mode and owner information to apply to replacement */
1132 1159 if (fstat(fd, &ar_stbuf) < 0) {
1133 1160 int err = errno;
1134 1161 (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT),
1135 1162 name, strerror(err));
1136 1163 (void) close(fd);
1137 1164 exit(1);
1138 1165 }
1139 1166 (void) close(fd);
1140 1167 new_archive = 0;
1141 1168 }
1142 1169
1143 1170
1144 1171 /*
1145 1172 * Register exit handler function to clean up after us if we exit
1146 1173 * before completing the new archive. atexit() is defined as
1147 1174 * only being able to fail due to memory exhaustion.
1148 1175 */
1149 1176 if (atexit(exit_cleanup) != 0) {
1150 1177 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
1151 1178 exit(1);
1152 1179 }
1153 1180
1154 1181 /*
1155 1182 * If a new archive, create it in place. If updating an archive,
1156 1183 * create the replacement under a temporary name and then rename it
1157 1184 * into place.
1158 1185 */
1159 1186 ar_outfile.path = new_archive ? name : make_tmpname(name);
1160 1187 ar_outfile.fd = open(ar_outfile.path, O_RDWR|O_CREAT|O_LARGEFILE, 0666);
1161 1188 if (ar_outfile.fd == -1) {
1162 1189 int err = errno;
1163 1190 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1164 1191 ar_outfile.path, strerror(err));
1165 1192 exit(1);
1166 1193 }
1167 1194
1168 1195 /* Output magic string */
1169 1196 arwrite(name, ar_outfile.fd, ARMAG, SARMAG);
1170 1197
1171 1198 /*
1172 1199 * The symbol table member is always first if present. Note that
1173 1200 * writesymtab() uses the member offsets computed by sizeofmembers()
1174 1201 * above.
1175 1202 */
1176 1203 if (found_obj)
1177 1204 writesymtab(name, ar_outfile.fd, nsyms, symlist,
1178 1205 symtbl_eltsize);
1179 1206
1180 1207 if (longnames) {
1181 1208 write_member_header(name, ar_outfile.fd, 0,
1182 1209 MSG_ORIG(MSG_STR_DSLASH), time(0), 0, 0, 0,
1183 1210 long_strtbl.used);
1184 1211 arwrite(name, ar_outfile.fd, long_strtbl.base,
1185 1212 long_strtbl.used);
1186 1213 }
1187 1214
1188 1215 /*
1189 1216 * The accuracy of the symbol table depends on our having calculated
1190 1217 * the size of the archive accurately to this point. If this is a
1191 1218 * debug build, verify it.
1192 1219 */
1193 1220 assert(arsize == lseek(ar_outfile.fd, 0, SEEK_CUR));
1194 1221
1195 1222 #ifndef XPG4
1196 1223 if (cmd_info->opt_flgs & v_FLAG) {
1197 1224 (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_WRITE),
1198 1225 cmd_info->arnam);
1199 1226 }
1200 1227 #endif
1201 1228
1202 1229 /*
1203 1230 * Fill pad_bytes array with newline characters. This array
1204 1231 * is used to supply padding bytes at the end of ELF objects.
1205 1232 * There can never be more tha PADSZ such bytes, so this number
1206 1233 * will always suffice.
1207 1234 */
1208 1235 for (pad_cnt = 0; pad_cnt < PADSZ; pad_cnt++)
1209 1236 pad_bytes[pad_cnt] = '\n';
1210 1237
1211 1238 for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1212 1239 /*
1213 1240 * We computed the expected offset for each ELF member and
1214 1241 * used those offsets to fill the symbol table. If this is
1215 1242 * a debug build, verify that the computed offset was right.
1216 1243 */
1217 1244 is_elf = (fptr->ar_flag & (F_CLASS32 | F_CLASS64)) != 0;
1218 1245 assert(!is_elf ||
1219 1246 (fptr->ar_offset == lseek(ar_outfile.fd, 0, SEEK_CUR)));
1220 1247
1221 1248 /*
1222 1249 * NOTE:
1223 1250 * The mem_header->ar_name[] is set to a NULL string
1224 1251 * if the archive member header has some error.
1225 1252 * (See elf_getarhdr() man page.)
1226 1253 * It is set to NULL for example, the ar command reads
1227 1254 * the archive files created by SunOS 4.1 system.
1228 1255 * See c block comment in cmd.c, "Incompatible Archive Header".
1229 1256 */
1230 1257 if (fptr->ar_name[0] == 0) {
1231 1258 fptr->ar_longname = fptr->ar_rawname;
1232 1259 (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME);
1233 1260 }
1234 1261 write_member_header(name, ar_outfile.fd, is_elf,
1235 1262 (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) ?
1236 1263 trimslash(fptr->ar_longname) : fptr->ar_name,
1237 1264 EC_WORD(fptr->ar_date), fptr->ar_uid, fptr->ar_gid,
1238 1265 fptr->ar_mode, fptr->ar_size + fptr->ar_padding);
1239 1266
1240 1267
1241 1268 if ((fptr->ar_flag & F_ELFRAW) == 0) {
1242 1269 /*
1243 1270 * The file doesn't come from the archive, and is
1244 1271 * therefore not already in memory(fptr->ar_contents)
1245 1272 * so open it and do a direct file-to-file transfer of
1246 1273 * its contents. We use the sendfile() system call
1247 1274 * to make the kernel do the transfer, so we don't have
1248 1275 * to buffer data in process, and we trust that the
1249 1276 * kernel will use an optimal transfer strategy.
1250 1277 */
1251 1278 if ((fd = open(fptr->ar_pathname, O_RDONLY)) == -1) {
1252 1279 int err = errno;
1253 1280 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1254 1281 fptr->ar_longname, strerror(err));
1255 1282 exit(1);
1256 1283 }
1257 1284 if (stat(fptr->ar_pathname, &stbuf) < 0) {
1258 1285 int err = errno;
1259 1286 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
1260 1287 fptr->ar_longname, strerror(err));
1261 1288 (void) close(fd);
1262 1289 exit(1);
1263 1290 }
1264 1291 off = 0;
1265 1292 if (sendfile(ar_outfile.fd, fd, &off,
1266 1293 stbuf.st_size) != stbuf.st_size) {
1267 1294 int err = errno;
1268 1295 (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
1269 1296 name, strerror(err));
1270 1297 exit(2);
1271 1298 }
1272 1299 (void) close(fd);
1273 1300 } else {
1274 1301 /* Archive member is in memory. Write it out */
1275 1302 arwrite(name, ar_outfile.fd, fptr->ar_contents,
1276 1303 fptr->ar_size);
1277 1304 }
1278 1305
1279 1306 /*
1280 1307 * All archive members are padded to at least a boundary of 2.
1281 1308 * The expression ((fptr->ar_size & 0x1) != 0) yields 1 for
1282 1309 * odd boundaries, and 0 for even ones. To this, we add
1283 1310 * whatever padding is needed for ELF objects.
1284 1311 */
1285 1312 pad_cnt = ((fptr->ar_size & 0x1) != 0) + fptr->ar_padding;
1286 1313 if (pad_cnt > 0)
1287 1314 arwrite(name, ar_outfile.fd, pad_bytes, pad_cnt);
1288 1315 }
1289 1316
1290 1317 /*
1291 1318 * All archive output is done.
1292 1319 */
1293 1320 if (close(ar_outfile.fd) < 0) {
1294 1321 int err = errno;
1295 1322 (void) fprintf(stderr, MSG_INTL(MSG_SYS_CLOSE), ar_outfile.path,
1296 1323 strerror(err));
1297 1324 exit(1);
1298 1325 }
1299 1326 ar_outfile.fd = -1; /* Prevent removal on exit */
1300 1327 (void) elf_end(cmd_info->arf);
1301 1328 (void) close(cmd_info->afd);
1302 1329
1303 1330 /*
1304 1331 * If updating an existing archive, rename the new version on
1305 1332 * top of the original.
1306 1333 */
1307 1334 if (!new_archive) {
1308 1335 /*
1309 1336 * Prevent the replacement of the original archive from
1310 1337 * being interrupted, to lower the possibility of an
1311 1338 * interrupt destroying a pre-existing archive.
1312 1339 */
1313 1340 establish_sighandler(SIG_IGN);
1314 1341
1315 1342 if (rename(ar_outfile.path, name) < 0) {
1316 1343 int err = errno;
1317 1344 (void) fprintf(stderr, MSG_INTL(MSG_SYS_RENAME),
1318 1345 ar_outfile.path, name, strerror(err));
1319 1346 (void) unlink(ar_outfile.path);
1320 1347 exit(1);
1321 1348 }
1322 1349 (void) chmod(name, ar_stbuf.st_mode & 0777);
1323 1350 if (chown(name, ar_stbuf.st_uid, ar_stbuf.st_gid) >= 0)
1324 1351 (void) chmod(name, ar_stbuf.st_mode & 07777);
1325 1352
1326 1353 }
1327 1354 }
1328 1355
1329 1356 /*
1330 1357 * Examine all the archive members, enter any member names longer than
1331 1358 * 15 characters into the long name string table, and count the number
1332 1359 * of names found.
1333 1360 *
1334 1361 * Returns the size of the resulting archive member, including the
1335 1362 * member header.
1336 1363 */
1337 1364 static size_t
1338 1365 mklong_tab(void)
1339 1366 {
1340 1367 ARFILE *fptr;
1341 1368 size_t longnames = 0;
1342 1369
1343 1370 for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1344 1371 if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) {
1345 1372 longnames++;
1346 1373 savelongname(fptr);
1347 1374 }
1348 1375 }
1349 1376
1350 1377 /* round up table that keeps the long filenames */
1351 1378 if (longnames > 0)
1352 1379 strtbl_pad(&long_strtbl, pad(long_strtbl.used, 4), '\n');
1353 1380
1354 1381 return (longnames);
1355 1382 }
1356 1383
1357 1384 /*
1358 1385 * Write 32/64-bit words into buffer in archive symbol table
1359 1386 * standard byte order (MSB).
1360 1387 */
1361 1388 static char *
1362 1389 sputl32(uint32_t n, char *cp)
1363 1390 {
1364 1391 *cp++ = n >> 24;
1365 1392 *cp++ = n >> 16;
1366 1393 *cp++ = n >> 8;
1367 1394
1368 1395 *cp++ = n & 255;
1369 1396
1370 1397 return (cp);
1371 1398 }
1372 1399
1373 1400 static char *
1374 1401 sputl64(uint64_t n, char *cp)
1375 1402 {
1376 1403 *cp++ = n >> 56;
1377 1404 *cp++ = n >> 48;
1378 1405 *cp++ = n >> 40;
1379 1406 *cp++ = n >> 32;
1380 1407
1381 1408 *cp++ = n >> 24;
1382 1409 *cp++ = n >> 16;
1383 1410 *cp++ = n >> 8;
1384 1411
1385 1412 *cp++ = n & 255;
1386 1413
1387 1414 return (cp);
1388 1415 }
1389 1416
1390 1417 static int
1391 1418 search_sym_tab(const char *arname, ARFILE *fptr, Elf *elf, Elf_Scn *scn,
1392 1419 size_t *nsyms, ARFILEP **symlist, size_t *num_errs)
1393 1420 {
1394 1421 Elf_Data *str_data, *sym_data; /* string table, symbol table */
1395 1422 Elf_Scn *str_scn;
1396 1423 GElf_Sxword no_of_symbols;
1397 1424 GElf_Shdr shdr;
1398 1425 int counter;
1399 1426 int str_shtype;
1400 1427 char *symname;
1401 1428 static ARFILEP *sym_ptr = 0;
1402 1429 static ARFILEP *nextsym = NULL;
1403 1430 static int syms_left = 0;
1404 1431 char *fname = fptr->ar_pathname;
1405 1432
1406 1433 (void) gelf_getshdr(scn, &shdr);
1407 1434 str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */
1408 1435 if (str_scn == NULL) {
1409 1436 if (fname != NULL)
1410 1437 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
1411 1438 fname, elf_errmsg(-1));
1412 1439 else
1413 1440 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
1414 1441 arname, fptr->ar_longname, elf_errmsg(-1));
1415 1442 (*num_errs)++;
1416 1443 return (-1);
1417 1444 }
1418 1445
1419 1446 no_of_symbols = shdr.sh_size / shdr.sh_entsize;
1420 1447 if (no_of_symbols == -1) {
1421 1448 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_01));
1422 1449 return (-1);
1423 1450 }
1424 1451
1425 1452 (void) gelf_getshdr(str_scn, &shdr);
1426 1453 str_shtype = shdr.sh_type;
1427 1454 if (str_shtype == -1) {
1428 1455 if (fname != NULL)
1429 1456 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
1430 1457 fname, elf_errmsg(-1));
1431 1458 else
1432 1459 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
1433 1460 arname, fptr->ar_longname, elf_errmsg(-1));
1434 1461 (*num_errs)++;
1435 1462 return (-1);
1436 1463 }
1437 1464
1438 1465 /* This test must happen before testing the string table. */
1439 1466 if (no_of_symbols == 1)
1440 1467 return (0); /* no symbols; 0th symbol is the non-symbol */
1441 1468
1442 1469 if (str_shtype != SHT_STRTAB) {
1443 1470 if (fname != NULL)
1444 1471 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_FILE),
1445 1472 fname);
1446 1473 else
1447 1474 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_AR),
1448 1475 arname, fptr->ar_longname);
1449 1476 return (0);
1450 1477 }
1451 1478 str_data = 0;
1452 1479 if ((str_data = elf_getdata(str_scn, str_data)) == 0) {
1453 1480 if (fname != NULL)
1454 1481 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_FILE),
1455 1482 fname);
1456 1483 else
1457 1484 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_AR),
1458 1485 arname, fptr->ar_longname);
1459 1486 return (0);
1460 1487 }
1461 1488 if (str_data->d_size == 0) {
1462 1489 if (fname != NULL)
1463 1490 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_FILE),
1464 1491 fname);
1465 1492 else
1466 1493 (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_AR),
1467 1494 arname, fptr->ar_longname);
1468 1495 return (0);
1469 1496 }
1470 1497 sym_data = 0;
1471 1498 if ((sym_data = elf_getdata(scn, sym_data)) == NULL) {
1472 1499 if (fname != NULL)
1473 1500 (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_FILE),
1474 1501 fname, elf_errmsg(-1));
1475 1502 else
1476 1503 (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_AR),
1477 1504 arname, fptr->ar_longname, elf_errmsg(-1));
1478 1505 return (0);
1479 1506 }
1480 1507
1481 1508 /* start at 1, first symbol entry is ignored */
1482 1509 for (counter = 1; counter < no_of_symbols; counter++) {
1483 1510 GElf_Sym sym;
1484 1511 (void) gelf_getsym(sym_data, counter, &sym);
1485 1512
1486 1513 symname = (char *)(str_data->d_buf) + sym.st_name;
1487 1514
1488 1515 if (((GELF_ST_BIND(sym.st_info) == STB_GLOBAL) ||
1489 1516 (GELF_ST_BIND(sym.st_info) == STB_WEAK)) &&
1490 1517 (sym.st_shndx != SHN_UNDEF)) {
1491 1518 if (!syms_left) {
1492 1519 sym_ptr = malloc((SYMCHUNK+1)
1493 1520 * sizeof (ARFILEP));
1494 1521 if (sym_ptr == NULL) {
1495 1522 int err = errno;
1496 1523 (void) fprintf(stderr,
1497 1524 MSG_INTL(MSG_MALLOC),
1498 1525 strerror(err));
1499 1526 exit(1);
1500 1527 }
1501 1528 syms_left = SYMCHUNK;
1502 1529 if (nextsym)
1503 1530 *nextsym = (ARFILEP)sym_ptr;
1504 1531 else
1505 1532 *symlist = sym_ptr;
1506 1533 nextsym = sym_ptr;
1507 1534 }
1508 1535 sym_ptr = nextsym;
1509 1536 nextsym++;
1510 1537 syms_left--;
1511 1538 (*nsyms)++;
1512 1539 *sym_ptr = fptr;
1513 1540 savename(symname); /* put name in the archiver's */
1514 1541 /* symbol table string table */
1515 1542 }
1516 1543 }
1517 1544 return (0);
1518 1545 }
1519 1546
1520 1547 /*
1521 1548 * Get the output file size
1522 1549 */
1523 1550 static size_t
1524 1551 sizeofmembers(size_t psum)
1525 1552 {
1526 1553 size_t sum = 0;
1527 1554 ARFILE *fptr;
1528 1555 size_t hdrsize = sizeof (struct ar_hdr);
1529 1556
1530 1557 for (fptr = listhead; fptr; fptr = fptr->ar_next) {
1531 1558 fptr->ar_offset = psum + sum;
1532 1559 sum += fptr->ar_size;
1533 1560 if (fptr->ar_size & 01)
1534 1561 sum++;
1535 1562 sum += hdrsize;
1536 1563
1537 1564 /*
1538 1565 * If the current item, and the next item are both ELF
1539 1566 * objects, then add padding to current item so that the
1540 1567 * data in the next item will have PADSZ alignment.
1541 1568 *
1542 1569 * In any other case, set the padding to 0. If the
1543 1570 * item comes from another archive, it may be carrying
1544 1571 * a non-zero padding value from that archive that does
1545 1572 * not apply to the one we are about to build.
1546 1573 */
1547 1574 if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) &&
1548 1575 fptr->ar_next &&
1549 1576 (fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) {
1550 1577 fptr->ar_padding = pad(psum + sum + hdrsize, PADSZ);
1551 1578 sum += fptr->ar_padding;
1552 1579 } else {
1553 1580 fptr->ar_padding = 0;
1554 1581 }
1555 1582 }
1556 1583 return (sum);
1557 1584 }
1558 1585
1559 1586 /*
1560 1587 * Compute the size of the symbol table archive member.
1561 1588 *
1562 1589 * entry:
1563 1590 * nsyms - # of symbols in the table
1564 1591 * found_obj - TRUE if the archive contains any ELF objects
1565 1592 * eltsize - Size of the integer type to use for the symbol
1566 1593 * table. 4 for 32-bit tables, and 8 for 64-bit tables.
1567 1594 */
1568 1595 static size_t
1569 1596 sizeof_symtbl(size_t nsyms, int found_obj, size_t eltsize)
1570 1597 {
1571 1598 size_t sum = 0;
1572 1599
1573 1600 if (found_obj) {
1574 1601 /* Member header, symbol count, and one slot per symbol */
1575 1602 sum += sizeof (struct ar_hdr) + ((nsyms + 1) * eltsize);
1576 1603 sum += sym_strtbl.used;
1577 1604 }
1578 1605
1579 1606 return (sum);
1580 1607 }
1581 1608
1582 1609 static void
1583 1610 arwrite(const char *name, int nfd, const char *dst, size_t size) {
1584 1611 if (write(nfd, dst, size) != size) {
1585 1612 int err = errno;
1586 1613 (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
1587 1614 name, strerror(err));
1588 1615 exit(2);
1589 1616 }
1590 1617 }
1591 1618
1592 1619 static const char *
1593 1620 make_tmpname(const char *filename) {
1594 1621 char *slash, *tmpname;
1595 1622 size_t prefix_cnt = 0;
1596 1623
1597 1624 /*
1598 1625 * If there is a path prefix in front of the filename, we
1599 1626 * want to put the temporary file in the same directory.
1600 1627 * Determine the length of the path.
1601 1628 */
1602 1629 slash = strrchr(filename, '/');
1603 1630 if (slash != NULL)
1604 1631 prefix_cnt = slash - filename + 1;
1605 1632 tmpname = malloc(prefix_cnt + MSG_STR_MKTEMP_SIZE + 1);
1606 1633 if (tmpname == NULL) {
1607 1634 int err = errno;
1608 1635 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
1609 1636 exit(1);
1610 1637 }
1611 1638
1612 1639 if (prefix_cnt > 0)
1613 1640 (void) strncpy(tmpname, filename, prefix_cnt);
1614 1641 (void) strcpy(tmpname + prefix_cnt, MSG_ORIG(MSG_STR_MKTEMP));
1615 1642 (void) mktemp(tmpname);
1616 1643
1617 1644 return (tmpname);
1618 1645 }
↓ open down ↓ |
956 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX