file.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "gelf.h"
#include "inc.h"
#include "extern.h"
static char *str_base; /* start of string table for names */
static char *str_top; /* pointer to next available location */
static int pad_symtab;
/*
* Function Prototypes
*/
static long mklong_tab(int *);
static char *trimslash(char *s);
static int writesymtab(char *, long, ARFILEP *);
static void savename(char *);
static void savelongname(ARFILE *, char *);
static void sputl(long, char *);
int new_archive);
static int sizeofmembers();
static int sizeofnewarchive(int, int);
long *, ARFILEP **, int *);
#ifdef BROWSER
static void sbrowser_search_stab(Elf *, int, int, char *);
#endif
int
{
int fd;
exit(1);
}
/* archive does not exist yet, may have to create one */
return (fd);
} else {
/* problem other than "does not exist" */
exit(1);
}
}
cmd = ELF_C_READ;
PLAIN_ERROR, (char *)0, arnam);
exit(1);
}
return (fd);
}
ARFILE *
{
char *tmp_rawname, *file_rawname;
if (fd == -1)
return (NULL); /* the archive doesn't exist */
return (NULL); /* the archive is empty or have hit the end */
exit(1);
}
/* zip past special members like the symbol and string table members */
return (NULL);
/* the archive is empty or have hit the end */
exit(0);
}
}
/*
* NOTE:
* The mem_header->ar_name[] is set to a NULL string
* if the archive member header has some error.
* (See elf_getarhdr() man page.)
* It is set to NULL for example, the ar command reads
* the archive files created by SunOS 4.1 system.
* See c block comment in cmd.c, "Incompatible Archive Header".
*/
if ((file->ar_longname
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
if ((file->ar_rawname
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
while (!isspace(*tmp_rawname) &&
file_rawname++;
tmp_rawname++;
}
if (!(*tmp_rawname == '\0'))
*file_rawname = '\0';
/* reverse logic */
== NULL) {
if (ptr != 0) {
exit(1);
}
}
}
return (file);
}
ARFILE *
newfile()
{
static int count = 0;
if (count == 0) {
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
}
count--;
if (listhead)
else
return (fileptr);
}
static char *
trimslash(char *s)
{
}
char *
trim(char *s)
{
;
while (p1 > s) {
if (*--p1 != '/')
break;
*p1 = 0;
}
p2 = s;
if (*p1 == '/')
return (p2);
}
static long
{
long mem_offset = 0;
int newfd;
long nsyms = 0;
int class = 0;
char *sbshstr;
char *sbshstrtp;
int sbstabsect = -1;
int sbstabstrsect = -1;
int num_errs = 0;
newfd = 0;
/* determine if file is coming from the archive or not */
/*
* I can use the saved elf descriptor.
*/
if ((newfd =
fptr->ar_pathname);
num_errs++;
continue;
}
(Elf *)0)) == 0) {
fptr->ar_pathname);
else
newfd = 0;
num_errs++;
continue;
}
PLAIN_ERROR, (char *)0,
fptr->ar_pathname);
else
PLAIN_ERROR, (char *)0);
if (newfd) {
newfd = 0;
}
continue;
}
} else {
PLAIN_ERROR, (char *)0);
exit(1);
}
} else if (class == ELFCLASS32)
fptr->ar_pathname);
else
num_errs++;
if (newfd) {
newfd = 0;
}
continue;
}
data = 0;
fptr->ar_pathname);
else
num_errs++;
if (newfd) {
newfd = 0;
}
continue;
}
PLAIN_ERROR, (char *)0,
fptr->ar_pathname);
else
PLAIN_ERROR, (char *)0);
if (newfd) {
newfd = 0;
}
num_errs++;
continue;
}
/* loop through sections to find symbol table */
scn = 0;
fptr->ar_pathname);
else
if (newfd) {
newfd = 0;
}
num_errs++;
continue;
}
*found_obj = 1;
scn,
&nsyms,
&num_errs) == -1) {
if (newfd) {
newfd = 0;
}
continue;
}
#ifdef BROWSER
/*
* XX64: sbrowser_search_stab() currently gets
* confused by sb-tabs in v9. at this
* point, no one knows what v9 sb-tabs are
* supposed to look like.
*/
/* if (shdr.sh_name != 0) { */
if ((class == ELFCLASS32) &&
sbshstrtp = (char *)
".stabstr") == 0) {
}
}
#endif
}
#ifdef BROWSER
elf,
sbstabsect = -1;
sbstabstrsect = -1;
}
#endif
}
mem_offset++;
if (newfd) {
newfd = 0;
}
} /* for */
if (num_errs)
exit(1);
return (nsyms);
}
/*
* This routine writes an archive symbol table for the
* output archive file. The symbol table is built if
* there was at least one object file specified.
* In rare case, there could be no symbol.
* In this case, str_top and str_base can not be used to
* make the string table. So the routine adjust the size
* and make a dummy string table. String table is needed
* by elf_getarsym().
*/
static int
{
int i, j;
long sym_tab_size = 0;
int sum = 0;
/*
* patch up archive pointers and write the symbol entries
*/
*str_top++ = '\0';
if (nsyms == 0)
sym_tab_size += 4;
(unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG);
exit(1);
}
exit(1);
}
if (!j) {
j = SYMCHUNK;
}
bptr += 4;
}
if (nsyms != 0) {
} else {
/*
* Writing a dummy string table.
*/
int i;
for (i = 0; i < 4; i++)
*dst++ = 0;
sum += 4;
}
/*
* The first member file is ELFCLASS64. We need to make the member
* to be placed at the 8 byte boundary.
*/
if (pad_symtab) {
int i;
for (i = 0; i < 4; i++)
*dst++ = 0;
sum += 4;
}
return (sum);
}
static void
{
char *p, *s;
unsigned int i;
int diff;
diff = 0;
if (str_base == (char *)0) {
/* no space allocated yet */
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
}
p = str_top;
do
NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
/*
* Re-adjust other pointers
*/
p += diff;
}
for (i = 0, s = symbol;
*p++ = *s++;
}
*p++ = '\0';
str_top = p;
}
static void
{
char *p, *s;
unsigned int i;
int diff;
static int bytes_used;
int index;
diff = 0;
if (str_base1 == (char *)0) {
/* no space allocated yet */
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
}
p = str_top1;
index = bytes_used;
do
== NULL) {
PLAIN_ERROR, (char *)0);
exit(1);
}
/*
* Re-adjust other pointers
*/
p += diff;
}
for (i = 0, s = fptr->ar_longname;
i++) {
*p++ = *s++;
}
*p++ = '/';
*p++ = '\n';
str_top1 = p;
}
char *
{
int i;
int longnames = 0;
long long_tab_size = 0;
long nsyms;
int new_archive = 0;
int arsize;
char *dst;
char *tmp_dst;
int nfd;
int found_obj = 0;
for (i = 0; signum[i]; i++)
/* started writing, cannot interrupt */
/* Is this a new archive? */
new_archive = 1;
}
}
else
new_archive = 0;
/*
* Calculate the size of the new archive
*/
/*
* Dummy symtab ?
*/
/*
* 4 + 4 = First 4 bytes to keep the number of symbols.
* The second 4 bytes for string table.
*/
if (arsize > AR_MAX_BYTES_IN_MEM) {
} else {
}
}
int diff;
}
if (longnames) {
(unsigned)0, (unsigned)0, (unsigned)0,
(long)long_tab_size, ARFMAG);
}
/*
* NOTE:
* The mem_header->ar_name[] is set to a NULL string
* if the archive member header has some error.
* (See elf_getarhdr() man page.)
* It is set to NULL for example, the ar command reads
* the archive files created by SunOS 4.1 system.
* See c block comment in cmd.c, "Incompatible Archive Header".
*/
}
else
ARFMAG);
/* file was not read in fptr->ar_contents during 'cmd' */
/* do it now */
FILE *f;
if (f == NULL) {
fptr->ar_longname);
exit(1);
} else {
sizeof (char),
fptr->ar_longname);
exit(1);
}
}
fclose(f);
} else {
}
}
tmp_dst++;
}
if (fptr->ar_padding) {
int i = fptr->ar_padding;
while (i) {
*tmp_dst++ = '\n';
--i;
}
}
}
/*
* All preparation for writing is done.
*/
/*
* Write out to the file
*/
if (new_archive) {
/*
* create a new file
*/
if (nfd == -1) {
exit(1);
}
} else {
/*
* Open the new file
*/
if (nfd == -1) {
exit(1);
}
}
#ifndef XPG4
PLAIN_ERROR, (char *)0,
}
#endif
if (!new_archive)
PLAIN_ERROR, (char *)0);
exit(2);
}
return (dst);
}
static long
mklong_tab(int *longnames)
{
long ret = 0;
(*longnames)++;
}
}
if (*longnames) {
/* round up table that keeps the long filenames */
*str_top1++ = '\n';
}
return (ret);
}
/* Put bytes in archive header in machine independent order. */
static void
{
*cp++ = n >> 24;
*cp++ = n >> 16;
*cp++ = n >> 8;
*cp++ = n & 255;
}
#ifdef BROWSER
static void
{
char *stabstrtab;
char *stabstroff;
char *symname;
int prevstabstrsz;
/* use the .stab and stabstr section index to find the data buffer */
if (stabid == -1) {
PLAIN_ERROR, (char *)0);
return;
}
return;
}
/*
* Zero length .stab sections have been produced by some compilers so
* ignore the section if this is the case.
*/
return;
if (stabstrid == -1) {
PLAIN_ERROR, (char *)0);
return;
}
if (stabstr_scn == NULL) {
return;
}
return;
}
PLAIN_ERROR, (char *)0);
return;
}
data = 0;
return;
}
PLAIN_ERROR, (char *)0);
return;
}
data = 0;
return;
}
PLAIN_ERROR, (char *)0);
return;
}
prevstabstrsz = 0;
}
}
}
}
#endif
static int
{
int counter;
int str_shtype;
char *symname;
static int syms_left = 0;
fname);
else
(*num_errs)++;
return (-1);
}
if (no_of_symbols == -1) {
PLAIN_ERROR, (char *)0);
return (-1);
}
if (str_shtype == -1) {
else
(*num_errs)++;
return (-1);
}
/* This test must happen before testing the string table. */
if (no_of_symbols == 1)
return (0); /* no symbols; 0th symbol is the non-symbol */
if (str_shtype != SHT_STRTAB) {
PLAIN_ERROR, (char *)0,
fname);
else
PLAIN_ERROR, (char *)0);
return (0);
}
str_data = 0;
PLAIN_ERROR, (char *)0,
fname);
else
PLAIN_ERROR, (char *)0);
return (0);
}
PLAIN_ERROR, (char *)0,
fname);
else
PLAIN_ERROR, (char *)0);
return (0);
}
sym_data = 0;
else
elf_errmsg(-1));
return (0);
}
/* start at 1, first symbol entry is ignored */
if (!syms_left) {
* sizeof (ARFILEP));
PLAIN_ERROR, (char *)0);
exit(1);
}
if (nextsym)
else
}
nextsym++;
syms_left--;
(*nsyms)++;
/* symbol table string table */
}
}
return (0);
}
/*
* Get the output file size
*/
static int
sizeofmembers(int psum)
{
int sum = 0;
sum++;
int remainder;
if (remainder) {
}
}
}
return (sum);
}
static int
{
int sum = 0;
if (nsyms) {
top++;
}
if (longnames) {
}
/*
* If the first member file is ELFCLASS64 type,
* we have to ensure the member contents will align
* on 8 byte boundary.
*/
sum += 4;
pad_symtab = 4;
}
}
return (sum);
}
static void
exit(2);
}
}
static char *
make_tmpname(char *filename) {
static char template[] = "arXXXXXX";
char *tmpname;
char c;
c = *slash;
*slash = 0;
sizeof (template) + 2);
*slash = c;
} else {
}
return (tmpname);
}
static int
int saved;
char buf[8192];
if (fromfd < 0)
return (-1);
if (tofd < 0) {
return (-1);
}
return (-1);
}
}
if (nread < 0) {
return (-1);
}
return (0);
}
static int
int exists;
struct stat s;
int ret = 0;
if (ret == 0) {
if (exists) {
}
} else {
}
} else {
}
return (ret);
}
static int
{
int sum = 0;
if (nsyms) {
top++;
}
if (longnames) {
}
/*
* If the first member file is ELFCLASS64 type,
* we have to ensure the member contents will align
* on 8 byte boundary.
*/
sum += 4;
}
}
return (sum);
}
static char *
{
register int i;
int arsize;
char *dst;
char *tmp_dst;
int nfd;
char *new_name;
FILE *f;
if (new_archive) {
if (nfd == -1) {
exit(1);
}
} else {
if (nfd == -1) {
exit(1);
}
}
if (arsize < 2048) {
arsize = 2048;
}
int diff;
}
if (longnames) {
(unsigned)0, (unsigned)0, (unsigned)0,
(long)long_tab_size, ARFMAG);
}
#ifndef XPG4
PLAIN_ERROR, (char *)0,
}
#endif
}
else
ARFMAG);
(void) fclose(f);
f = NULL;
}
if (f == NULL) {
fptr->ar_longname);
exit(1);
} else {
if ((fptr->ar_contents = (char *)
PLAIN_ERROR, (char *)0);
exit(1);
}
sizeof (char),
fptr->ar_longname);
exit(1);
}
}
fclose(f);
} else {
}
}
}
if (fptr->ar_padding) {
int i = fptr->ar_padding;
while (i) {
--i;
}
}
}
/*
* All preparation for writing is done.
*/
if (!new_archive) {
}
return (dst);
}