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