summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAli Bahrami <Ali.Bahrami@Oracle.COM>2010-07-08 09:23:43 -0600
committerAli Bahrami <Ali.Bahrami@Oracle.COM>2010-07-08 09:23:43 -0600
commitba7866cd2cbdf574f47d4e38a1301b90744dd677 (patch)
tree61774e774c951296df1a185c9b8004a5ba75739f /usr/src
parent65e70c04884b95e29d10e9933a3d55f0ec5af3be (diff)
downloadillumos-joyent-ba7866cd2cbdf574f47d4e38a1301b90744dd677.tar.gz
6952219 ld support for archives larger than 2 GB
PSARC/2010/224 Support for archives larger than 2 GB
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/Makefile8
-rw-r--r--usr/src/cmd/sgs/ar/Makefile.com43
-rw-r--r--usr/src/cmd/sgs/ar/Makefile.targ44
-rw-r--r--usr/src/cmd/sgs/ar/amd64/Makefile (renamed from usr/src/cmd/sgs/packages/common/admin)42
-rw-r--r--usr/src/cmd/sgs/ar/common/ar.msg134
-rw-r--r--usr/src/cmd/sgs/ar/common/cmd.c349
-rw-r--r--usr/src/cmd/sgs/ar/common/file.c1735
-rw-r--r--usr/src/cmd/sgs/ar/common/global.c32
-rw-r--r--usr/src/cmd/sgs/ar/common/inc.h264
-rw-r--r--usr/src/cmd/sgs/ar/common/lintsup.c (renamed from usr/src/cmd/sgs/ar/common/extern.h)24
-rw-r--r--usr/src/cmd/sgs/ar/common/main.c158
-rw-r--r--usr/src/cmd/sgs/ar/common/message.c314
-rw-r--r--usr/src/cmd/sgs/ar/i386/Makefile17
-rw-r--r--usr/src/cmd/sgs/ar/sparc/Makefile15
-rw-r--r--usr/src/cmd/sgs/ar/sparcv9/Makefile43
-rw-r--r--usr/src/cmd/sgs/dump/common/dump.c9
-rw-r--r--usr/src/cmd/sgs/dump/common/fcns.c23
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg12
-rw-r--r--usr/src/cmd/sgs/elfdump/common/main.c39
-rw-r--r--usr/src/cmd/sgs/include/_libelf.h1
-rw-r--r--usr/src/cmd/sgs/libelf/common/ar.c34
-rw-r--r--usr/src/cmd/sgs/libelf/common/decl.h4
-rw-r--r--usr/src/cmd/sgs/libelf/common/getarsym.c126
-rw-r--r--usr/src/cmd/sgs/libelf/common/llib-lelf1
-rw-r--r--usr/src/cmd/sgs/libelf/common/mapfile-vers1
-rw-r--r--usr/src/cmd/sgs/mcs/common/file.c6
-rw-r--r--usr/src/cmd/sgs/messages/Makefile.com6
-rw-r--r--usr/src/cmd/sgs/messages/sgs.ident4
-rw-r--r--usr/src/cmd/sgs/nm/common/nm.c2
-rw-r--r--usr/src/cmd/sgs/nm/i386/Makefile10
-rw-r--r--usr/src/cmd/sgs/packages/Makefile4
-rw-r--r--usr/src/cmd/sgs/packages/Makefile.com5
-rw-r--r--usr/src/cmd/sgs/packages/Makefile.lint6
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README2
-rw-r--r--usr/src/cmd/sgs/packages/common/prototype_com12
-rw-r--r--usr/src/cmd/sgs/packages/common/prototype_i3867
-rw-r--r--usr/src/cmd/sgs/packages/common/prototype_sparc7
-rw-r--r--usr/src/pkg/manifests/developer-object-file.mf2
38 files changed, 1754 insertions, 1791 deletions
diff --git a/usr/src/cmd/sgs/Makefile b/usr/src/cmd/sgs/Makefile
index 10483bb9f2..25c5486d0a 100644
--- a/usr/src/cmd/sgs/Makefile
+++ b/usr/src/cmd/sgs/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
#
include $(SRC)/cmd/Makefile.cmd
@@ -84,8 +83,7 @@ SUBDIRS= $(SUBDIRS-common) $(SUBDIRS-$(MACH))
# Messaging support
#
-POSUBDIRS= ar m4 nm \
- tsort yacc
+POSUBDIRS= m4 nm tsort yacc
POFILE= sgs.po
POFILES= $(POSUBDIRS:%=%/%.po)
@@ -93,7 +91,7 @@ MSGSUBDIRS= ld ldd libld liblddbg \
libldstab librtld rtld libelf \
ldprof libcrle pvs elfdump \
elfedit crle moe lari \
- librtld_db elfwrap
+ librtld_db elfwrap ar
MSGDIR= messages
diff --git a/usr/src/cmd/sgs/ar/Makefile.com b/usr/src/cmd/sgs/ar/Makefile.com
index e37d825ad4..2670d05404 100644
--- a/usr/src/cmd/sgs/ar/Makefile.com
+++ b/usr/src/cmd/sgs/ar/Makefile.com
@@ -19,44 +19,47 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
#
PROG= ar
XPG4PROG= ar
include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/sgs/Makefile.com
-COMOBJS= main.o file.o cmd.o global.o \
- message.o
+COMOBJ= main.o file.o cmd.o
-POFILE= ../ar.po
+BLTOBJ = msg.o
-OBJS= $(COMOBJS:%=objs/%)
-XPG4OBJS= $(COMOBJS:%=objs.xpg4/%)
+OBJS= $(BLTOBJ:%=objs/%) $(COMOBJ:%=objs/%)
+XPG4OBJS= $(BLTOBJ:%=objs.xpg4/%) $(COMOBJ:%=objs.xpg4/%)
LLDFLAGS = '-R$$ORIGIN/../../lib'
-CPPFLAGS= -I../../include $(CPPFLAGS.master)
+LLDFLAGS64 = '-R$$ORIGIN/../../../lib/$(MACH64)'
+CPPFLAGS= -I. -I../../include $(CPPFLAGS.master) -I$(ELFCAP)
CFLAGS += $(CCVERBOSE)
C99MODE= $(C99_ENABLE)
-LDLIBS += -lelf
-LINTFLAGS= -mx
-LINTFLAGS64= -mx -m64
-
-SED= sed
+LDLIBS += -lelf $(CONVLIBDIR) $(CONV_LIB) -lsendfile
+LINTFLAGS= -x
+LINTFLAGS64= -x
$(XPG4) := CPPFLAGS += -DXPG4
-SRCS= $(COMOBJS:%.o=../common/%.c)
-LINTSRCS= $(SRCS)
+BLTDEFS = msg.h
+BLTDATA = msg.c
+BLTMESG = $(SGSMSGDIR)/ar
+
+BLTFILES = $(BLTDEFS) $(BLTDATA) $(BLTMESG)
-CLEANFILES += $(OBJS) $(XPG4OBJS) $(LINTOUT)
+SGSMSGCOM = ../common/ar.msg
+SGSMSGTARG = $(SGSMSGCOM)
+SGSMSGALL = $(SGSMSGCOM)
+SGSMSGFLAGS += -h $(BLTDEFS) -d $(BLTDATA) -m $(BLTMESG) -n ar_msg
-# Building SUNWonld results in a call to the `package' target. Requirements
-# needed to run this application on older releases are established:
-# i18n support requires libintl.so.1 prior to 2.6
+SRCS= $(COMOBJ:%.o=../common/%.c) $(BLTDATA:%.o=$(SGSTOOLS)/common/%.c)
+LINTSRCS= $(SRCS) ../common/lintsup.c
-package := LDLIBS += /usr/lib/libintl.so.1
+CLEANFILES += $(LINTOUTS) $(BLTFILES)
diff --git a/usr/src/cmd/sgs/ar/Makefile.targ b/usr/src/cmd/sgs/ar/Makefile.targ
index 9a272b0de2..6d28736736 100644
--- a/usr/src/cmd/sgs/ar/Makefile.targ
+++ b/usr/src/cmd/sgs/ar/Makefile.targ
@@ -19,30 +19,29 @@
# CDDL HEADER END
#
#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
objs/%.o \
objs.xpg4/%.o: ../common/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
-all: $(PROG) $(XPG4)
+objs/%.o \
+objs.xpg4/%.o: %.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
clean:
- $(RM) $(CLEANFILES)
+ $(RM) $(OBJS) $(XPG4OBJS) $(CLEANFILES)
delete:
$(RM) $(PROG)
-install \
-package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK)
+catalog: $(BLTMESG)
-catalog: $(POFILE)
+.PARALLEL: $(LINTOUT32) $(LINTOUT64)
-lint: $(LINTOUT)
+lint: $(LINTOUT32) $(SGSLINTOUT)
$(PROG): $(OBJS)
$(LINK.c) -o $@ $(LLDFLAGS) $(OBJS) $(LDLIBS)
@@ -52,14 +51,6 @@ $(XPG4): $(XPG4OBJS)
$(LINK.c) -o $@ $(XPG4OBJS) $(LDLIBS)
$(POST_PROCESS)
-$(POFILE):
- $(RM) $@
- $(XGETTEXT) $(XGETFLAGS) ../common/main.c
- $(SED) "/^domain/d" < messages.po > $@
- $(XGETTEXT) -a $(XGETFLAGS) ../common/message.c
- $(SED) "/^domain/d" < messages.po >> $@
- $(RM) messages.po
-
$(OBJS): objs
$(XPG4OBJS): objs.xpg4
@@ -67,8 +58,17 @@ $(XPG4OBJS): objs.xpg4
objs objs.xpg4:
-@ mkdir -p $@
-$(LINTOUT): $(SRCS)
- perl ../../tools/lint_hdr.pl $(PROG) > $(LINTOUT)
- $(LINT.c) $(SRCS) $(LDLIBS) 2>&1 | tee -a $(LINTOUT)
-
include $(SRC)/cmd/Makefile.targ
+include $(SRC)/cmd/sgs/Makefile.targ
+
+# Derived source and header files (messaging).
+
+catalog: $(BLTMESG)
+
+chkmsg: $(SRCS)
+ sh $(CHKMSG) $(CHKMSGFLAGS) $(SRCS)
+
+$(BLTDEFS) + \
+$(BLTDATA) + \
+$(BLTMESG): $(SGSMSGALL)
+ $(SGSMSG) $(SGSMSGFLAGS) $(SGSMSGALL)
diff --git a/usr/src/cmd/sgs/packages/common/admin b/usr/src/cmd/sgs/ar/amd64/Makefile
index 2d57427f83..4077158a06 100644
--- a/usr/src/cmd/sgs/packages/common/admin
+++ b/usr/src/cmd/sgs/ar/amd64/Makefile
@@ -1,7 +1,4 @@
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
@@ -22,24 +19,27 @@
# CDDL HEADER END
#
-# This admin file can be used to force the installation of the
-# SUNWonld package on a system that already has it installed, without
-# having to first uninstall the existing instance. This is a generally
-# undesirable thing to do, but can be handy if you forget to uninstall
-# SUNWonld before BFUing the system. In that state, removing the
-# package can break your system, and the only safe route forward is
-# to install on top of the existing package.
#
-# # pkgadd -a admin -d SUNWonld
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
-mail=
-instance=overwrite
-partial=ask
-runlevel=nocheck
-idepend=nocheck
-rdepend=ask
-space=nocheck
-setuid=nocheck
-conflict=nocheck
-action=nocheck
+include ../Makefile.com
+
+.KEEP_STATE:
+
+LLDFLAGS = $(LLDFLAGS64)
+CONVLIBDIR = $(CONVLIBDIR64)
+ELFLIBDIR = $(ELFLIBDIR64)
+LDDBGLIBDIR = $(LDDBGLIBDIR64)
+LINTFLAGS64 += $(VAR_LINTFLAGS64)
+
+ROOTPROG = $(ROOTPROG64)
+
+all: $(PROG)
+
+install \
+package: all $(ROOTPROG64) $(ROOTCCSBINLINK64)
+
+
+include ../Makefile.targ
+include ../../Makefile.sub.64
diff --git a/usr/src/cmd/sgs/ar/common/ar.msg b/usr/src/cmd/sgs/ar/common/ar.msg
new file mode 100644
index 0000000000..f82a689966
--- /dev/null
+++ b/usr/src/cmd/sgs/ar/common/ar.msg
@@ -0,0 +1,134 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (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
+# or http://www.opensolaris.org/os/licensing.
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+@ _START_
+
+# Message file for cmd/sgs/ar.
+
+@ MSG_ID_AR
+
+@ MSG_USAGE "usage: ar -d[-SvV] archive file ...\n \
+ ar -m[-abiSvV] [posname] archive file ...\n \
+ ar -p[-vV][-sS] archive [file ...]\n \
+ ar -q[-cuvSV] [-abi] [posname] [file ...]\n \
+ ar -r[-cuvSV] [-abi] [posname] [file ...]\n \
+ ar -t[-vV][-sS] archive [file ...]\n \
+ ar -x[-vV][-sSCT] archive [file ...]\n"
+
+@ MSG_MALLOC "ar: could not allocate memory: %s\n"
+@ MSG_TOOBIG4G "ar: archive size exceeds capabilities of 32-bit \
+ process\n"
+
+@ MSG_USAGE_01 "ar: one of [drqtpmx] must be specified\n"
+@ MSG_USAGE_02 "ar: -%c requires an operand\n"
+@ MSG_USAGE_03 "ar: bad option: -%c\n"
+@ MSG_USAGE_04 "ar: only one of [drqtpmx] allowed\n"
+@ MSG_USAGE_05 "ar: abi not allowed with q\n"
+@ MSG_USAGE_06 "ar: %s taken as mandatory 'posname' with keys 'abi'\n"
+
+@ MSG_INTERNAL_01 "ar: internal error: cannot tell whether file is \
+ included in archive or not\n"
+@ MSG_INTERNAL_02 "ar: internal header generation error\n"
+
+@ MSG_SYS_OPEN "ar: cannot open %s: %s\n"
+@ MSG_SYS_CLOSE "ar: cannot close %s: %s\n"
+@ MSG_SYS_WRITE "ar: %s: cannot write: %s\n"
+@ MSG_SYS_STAT "ar: cannot stat %s: %s\n"
+@ MSG_SYS_RENAME "ar: cannot rename %s to %s: %s\n"
+
+@ MSG_NOT_FOUND_AR "ar: archive %s not found\n"
+@ MSG_NOT_FOUND_POSNAM "ar: posname %s: not found\n"
+@ MSG_NOT_FOUND_FILE "ar: %s not found\n"
+
+@ MSG_ELF_LIB_FILE "ar: %s caused libelf error: %s\n"
+@ MSG_ELF_LIB_AR "ar: %s(%s) libelf error: %s\n"
+@ MSG_ELF_BEGIN_FILE "ar: cannot elf_begin() %s: %s\n"
+@ MSG_ELF_GETDATA_FILE "ar: %s has bad elf format: %s\n"
+@ MSG_ELF_GETDATA_AR "ar: %s(%s) has bad elf format: %s\n"
+@ MSG_ELF_GETSCN_FILE "ar: %s has no section header or bad elf format: %s\n"
+@ MSG_ELF_GETSCN_AR "ar: %s(%s) has no section header or bad elf \
+ format: %s\n"
+@ MSG_ELF_MALARCHIVE "ar: %s: offset %lld: malformed archive: %s\n"
+@ MSG_ELF_RAWFILE "ar: elf_rawfile() failed: %s\n"
+@ MSG_ELF_VERSION "ar: libelf.a out of date: %s\n"
+@ MSG_W_ELF_NODATA_FILE "ar: %s has no data in section header table\n"
+@ MSG_W_ELF_NODATA_AR "ar: %s(%s) has no data in section header table\n"
+
+@ MSG_BER_MES_CREATE "ar: creating %s\n"
+@ MSG_BER_MES_WRITE "ar: writing %s\n"
+
+@ MSG_SYMTAB_01 "ar: symbol table entry size is 0\n"
+@ MSG_SYMTAB_NOSTR_FILE "ar: %s has no string table for symbol names\n"
+@ MSG_SYMTAB_NOSTR_AR "ar: %s(%s) has no string table for symbol names\n"
+@ MSG_SYMTAB_NODAT_FILE "ar: %s has no data in string table\n"
+@ MSG_SYMTAB_NODAT_AR "ar: %s(%s) no data in string table\n"
+@ MSG_SYMTAB_ZDAT_FILE "ar: %s has no data in string table: size is 0\n"
+@ MSG_SYMTAB_ZDAT_AR "ar: %s(%s) no data in string table: size is 0\n"
+
+
+@ MSG_PATHCONF "ar: -T failed to calculate file name length: %s\n"
+@ MSG_LOCALTIME "ar: don't have enough space to store the date\n"
+@ MSG_NOT_ARCHIVE "ar: %s not in archive format\n"
+@ MSG_OVERRIDE_WARN "ar: %s already exists. Will not be extracted\n"
+
+@ MSG_ERR_LONGSTRTBLSZ "ar: archive format limit: long name string table \
+ would exceed 4GB\n"
+@ MSG_ERR_MEMBER4G "ar: archive format limit: individual archive \
+ members are limited to 4GB: %s\n"
+
+@ _END_
+
+# The following strings represent reserved words, files, pathnames and symbols.
+# Reference to this strings is via the MSG_ORIG() macro, and thus no message
+# translation is required.
+
+@ MSG_STR_OPTIONS ":a:b:i:vucsrdxtplmqVCTzMS"
+@ MSG_SUNW_OST_SGS "SUNW_OST_SGS"
+
+@ MSG_STR_EMPTY ""
+@ MSG_STR_HYPHEN "-"
+@ MSG_STR_PERIOD "."
+@ MSG_STR_LCR "r"
+@ MSG_STR_SLASH "/"
+@ MSG_STR_DSLASH "//"
+@ MSG_STR_SYM64 "/SYM64/"
+
+# Format for full member header
+#
+@ MSG_MH_FORMAT "%-16s%-12d%-6u%-6u%-8o%-10lld%-2s"
+
+@ MSG_FMT_VERSION "ar: %s %s\n"
+@ MSG_FMT_P_TITLE "\n<%s>\n\n"
+@ MSG_FMT_T_IDSZ "%6d/%6d%7lld"
+@ MSG_FMT_T_DATE "%b %e %H:%M %Y"
+@ MSG_FMT_SPSTRSP " %s "
+@ MSG_FMT_STRNL "%s\n"
+@ MSG_FMT_FILE "%c - %s\n"
+@ MSG_FMT_LLINT "/%lld"
+
+@ MSG_CMD_SWAP "/usr/sbin/swap -s"
+
+# Template for use with mktemp()
+@ MSG_STR_MKTEMP "arXXXXXX"
diff --git a/usr/src/cmd/sgs/ar/common/cmd.c b/usr/src/cmd/sgs/ar/common/cmd.c
index d7ea1875ac..4ed18765f6 100644
--- a/usr/src/cmd/sgs/ar/common/cmd.c
+++ b/usr/src/cmd/sgs/ar/common/cmd.c
@@ -2,9 +2,8 @@
* 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.
+ * Common Development and Distribution License (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
* or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -30,8 +28,6 @@
*
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Incompatible Archive Header
*
@@ -70,38 +66,34 @@
*/
#include "inc.h"
-#include "extern.h"
/*
- * Function prototypes
+ * Forward Declarations
*/
-static char *match(char *, Cmd_info *);
-
-static void cleanup(Cmd_info *);
-static void movefil(ARFILE *, struct stat *);
-static void mesg(int, char *, Cmd_info *);
-static void ar_select(int *, unsigned long);
-
-static FILE *stats(char *, struct stat *);
-
-static int create_extract(ARFILE *, int, int, Cmd_info *);
+static void ar_select(int *, unsigned long);
+static void cleanup(Cmd_info *);
+static int create_extract(ARFILE *, int, int, Cmd_info *);
+static char *match(char *, Cmd_info *);
+static void mesg(int, char *, Cmd_info *);
+static void movefil(ARFILE *, struct stat *);
+static FILE *stats(char *, struct stat *);
/*
* Commands
*/
-int
+void
rcmd(Cmd_info *cmd_info)
{
- FILE *f;
- ARFILE *fileptr;
- ARFILE *abifile = NULL;
- ARFILE *backptr = NULL;
- ARFILE *endptr;
- ARFILE *moved_files;
- ARFILE *prev_entry, *new_listhead, *new_listend;
- int deleted;
- struct stat stbuf;
- char *gfile;
+ FILE *f;
+ ARFILE *fileptr;
+ ARFILE *abifile = NULL;
+ ARFILE *backptr = NULL;
+ ARFILE *endptr;
+ ARFILE *moved_files;
+ ARFILE *prev_entry, *new_listhead, *new_listend;
+ int deleted;
+ struct stat stbuf;
+ char *gfile;
new_listhead = NULL;
new_listend = NULL;
@@ -110,7 +102,7 @@ rcmd(Cmd_info *cmd_info)
for (fileptr = getfile(cmd_info);
fileptr; fileptr = getfile(cmd_info)) {
deleted = 0;
- if (!abifile && cmd_info-> ponam &&
+ if (!abifile && cmd_info->ponam &&
strcmp(fileptr->ar_longname, cmd_info->ponam) == 0)
abifile = fileptr;
else if (!abifile)
@@ -125,16 +117,18 @@ rcmd(Cmd_info *cmd_info)
*/
f = stats(gfile, &stbuf); /* gfile is set by match */
if (f == NULL) {
- if (cmd_info->namc)
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno),
- gfile);
+ if (cmd_info->namc) {
+ int err = errno;
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_SYS_OPEN),
+ gfile, strerror(err));
+ }
/*
* Created
*/
mesg('c', gfile, cmd_info);
} else {
- if (opt_FLAG(cmd_info, u_FLAG) &&
+ if ((cmd_info->opt_flgs & u_FLAG) &&
stbuf.st_mtime <= fileptr->ar_date) {
(void) fclose(f);
continue;
@@ -147,9 +141,7 @@ rcmd(Cmd_info *cmd_info)
/*
* Clear the previous contents.
*/
- if (fileptr->ar_flag & F_MALLOCED)
- free(fileptr->ar_contents);
- else if (fileptr->ar_flag & F_ELFRAW) {
+ if (fileptr->ar_flag & F_ELFRAW) {
/*
* clear ar_elf
*/
@@ -157,59 +149,23 @@ rcmd(Cmd_info *cmd_info)
fileptr->ar_elf = 0;
}
/* clear 'ar_flag' */
- fileptr->ar_flag &=
- ~(F_ELFRAW | F_MMAPED | F_MALLOCED);
- if ((cmd_info->OPT_flgs & M_FLAG) == 0) {
- if ((cmd_info->bytes_in_mem +
- stbuf.st_size)
- < AR_MAX_BYTES_IN_MEM) {
- if ((fileptr->ar_contents =
- malloc(ROUNDUP(
- stbuf.st_size))) == NULL) {
- error_message(
- MALLOC_ERROR,
- PLAIN_ERROR,
- (char *)0);
- exit(1);
- }
- fileptr->ar_flag &=
- ~(F_ELFRAW | F_MMAPED);
- fileptr->ar_flag |= F_MALLOCED;
- if (fread(fileptr->ar_contents,
- sizeof (char),
- stbuf.st_size, f) !=
- stbuf.st_size) {
- error_message(
- SYS_READ_ERROR,
- SYSTEM_ERROR,
- strerror(errno),
- fileptr->
- ar_longname);
- exit(1);
- }
- cmd_info->bytes_in_mem +=
- stbuf.st_size;
- }
- } else {
- if ((fileptr->ar_contents = (char *)
- mmap(0, stbuf.st_size,
- PROT_READ,
- MAP_SHARED,
- fileno(f), 0)) == (char *)-1) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- fileptr->ar_flag &=
- ~(F_ELFRAW | F_MALLOCED);
- fileptr->ar_flag |= F_MMAPED;
- }
+ fileptr->ar_flag &= ~F_ELFRAW;
+
+ /*
+ * Defer reading contents until needed, and
+ * then use an in-kernel file-to-file transfer
+ * to avoid excessive in-process memory use.
+ */
+ fileptr->ar_contents = NULL;
+
if (fileptr->ar_pathname != NULL)
free(fileptr->ar_pathname);
if ((fileptr->ar_pathname =
malloc(strlen(gfile) + 1)) == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
@@ -252,8 +208,8 @@ rcmd(Cmd_info *cmd_info)
if (cmd_info->ponam && endptr &&
(((moved_files = endptr->ar_next) != NULL) || new_listhead)) {
if (!abifile) {
- error_message(NOT_FOUND_02_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->ponam);
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM),
+ cmd_info->ponam);
exit(2);
}
endptr->ar_next = NULL;
@@ -269,7 +225,7 @@ rcmd(Cmd_info *cmd_info)
moved_files = new_listhead;
}
/* 2: insert at appropriate position... */
- if (opt_FLAG(cmd_info, b_FLAG))
+ if (cmd_info->opt_flgs & b_FLAG)
abifile = backptr;
if (abifile) {
listend->ar_next = abifile->ar_next;
@@ -280,12 +236,11 @@ rcmd(Cmd_info *cmd_info)
}
listend = endptr;
} else if (cmd_info->ponam && !abifile)
- error_message(NOT_FOUND_02_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->ponam);
- return (0);
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM),
+ cmd_info->ponam);
}
-int
+void
dcmd(Cmd_info *cmd_info)
{
ARFILE *fptr;
@@ -319,25 +274,25 @@ dcmd(Cmd_info *cmd_info)
backptr = fptr;
}
}
- return (0);
}
-int
+void
xcmd(Cmd_info *cmd_info)
{
- int f;
- ARFILE *next;
- int rawname = 0;
- int f_len = 0;
+ int f;
+ ARFILE *next;
+ int rawname = 0;
+ long f_len = 0;
/*
* If -T is specified, get the maximum file name length.
*/
- if (cmd_info->OPT_flgs & T_FLAG) {
- f_len = pathconf(".", _PC_NAME_MAX);
+ if (cmd_info->opt_flgs & T_FLAG) {
+ f_len = pathconf(MSG_ORIG(MSG_STR_PERIOD), _PC_NAME_MAX);
if (f_len == -1) {
- error_message(PATHCONF_ERROR,
- SYSTEM_ERROR, strerror(errno));
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_PATHCONF),
+ strerror(err));
exit(1);
}
}
@@ -362,10 +317,11 @@ xcmd(Cmd_info *cmd_info)
if (write(f, next->ar_contents,
(unsigned)next->ar_size) !=
next->ar_size) {
- error_message(SYS_WRITE_ERROR,
- SYSTEM_ERROR,
- strerror(errno),
- next->ar_rawname);
+ int err = errno;
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_SYS_WRITE),
+ next->ar_rawname,
+ strerror(err));
exit(1);
}
} else {
@@ -376,10 +332,11 @@ xcmd(Cmd_info *cmd_info)
if (write(f, next->ar_contents,
(unsigned)next->ar_size) !=
next->ar_size) {
- error_message(SYS_WRITE_ERROR,
- SYSTEM_ERROR,
- strerror(errno),
- next->ar_longname);
+ int err = errno;
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_SYS_WRITE),
+ next->ar_longname,
+ strerror(err));
exit(1);
}
}
@@ -389,10 +346,9 @@ xcmd(Cmd_info *cmd_info)
}
rawname = 0;
} /* for */
- return (0);
}
-int
+void
pcmd(Cmd_info *cmd_info)
{
ARFILE *next;
@@ -406,19 +362,19 @@ pcmd(Cmd_info *cmd_info)
* Refer to "Incompatible Archive Header"
* blocked comment at the beginning of this file.
*/
- if (opt_FLAG(cmd_info, v_FLAG)) {
+ if (cmd_info->opt_flgs & v_FLAG) {
(void) fprintf(stdout,
- "\n<%s>\n\n", next->ar_longname);
+ MSG_ORIG(MSG_FMT_P_TITLE),
+ next->ar_longname);
(void) fflush(stdout);
}
(void) fwrite(next->ar_contents, sizeof (char),
next->ar_size, stdout);
}
}
- return (0);
}
-int
+void
mcmd(Cmd_info *cmd_info)
{
ARFILE *fileptr;
@@ -462,17 +418,17 @@ mcmd(Cmd_info *cmd_info)
}
if (!tmphead)
- return (1);
+ return;
if (!cmd_info->ponam)
listend->ar_next = tmphead;
else {
if (!abifile) {
- error_message(NOT_FOUND_02_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->ponam);
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM),
+ cmd_info->ponam);
exit(2);
}
- if (opt_FLAG(cmd_info, b_FLAG))
+ if (cmd_info->opt_flgs & b_FLAG)
abifile = backptr2;
if (abifile) {
tmpend->ar_next = abifile->ar_next;
@@ -483,24 +439,23 @@ mcmd(Cmd_info *cmd_info)
}
}
(cmd_info->modified)++;
- return (0);
}
-int
+void
tcmd(Cmd_info *cmd_info)
{
ARFILE *next;
int **mp;
char buf[DATESIZE];
- int m1[] = {1, ROWN, 'r', '-'};
- int m2[] = {1, WOWN, 'w', '-'};
- int m3[] = {2, SUID, 's', XOWN, 'x', '-'};
- int m4[] = {1, RGRP, 'r', '-'};
- int m5[] = {1, WGRP, 'w', '-'};
- int m6[] = {2, SGID, 's', XGRP, 'x', '-'};
- int m7[] = {1, ROTH, 'r', '-'};
- int m8[] = {1, WOTH, 'w', '-'};
- int m9[] = {2, STXT, 't', XOTH, 'x', '-'};
+ int m1[] = {1, S_IRUSR, 'r', '-'};
+ int m2[] = {1, S_IWUSR, 'w', '-'};
+ int m3[] = {2, S_ISUID, 's', S_IXUSR, 'x', '-'};
+ int m4[] = {1, S_IRGRP, 'r', '-'};
+ int m5[] = {1, S_IWGRP, 'w', '-'};
+ int m6[] = {2, S_ISGID, 's', S_IXGRP, 'x', '-'};
+ int m7[] = {1, S_IROTH, 'r', '-'};
+ int m8[] = {1, S_IWOTH, 'w', '-'};
+ int m9[] = {2, S_ISVTX, 't', S_IXOTH, 'x', '-'};
int *m[10];
m[0] = m1;
@@ -523,49 +478,48 @@ tcmd(Cmd_info *cmd_info)
* Refer to "Incompatible Archive Header"
* blocked comment at the beginning of this file.
*/
- if (opt_FLAG(cmd_info, v_FLAG)) {
+ if (cmd_info->opt_flgs & v_FLAG) {
for (mp = &m[0]; mp < &m[9]; )
ar_select(*mp++, next->ar_mode);
- (void) fprintf(stdout, "%6d/%6d", next->ar_uid,
- next->ar_gid);
- (void) fprintf(stdout, "%7ld", next->ar_size);
+ (void) fprintf(stdout, MSG_ORIG(MSG_FMT_T_IDSZ),
+ next->ar_uid, next->ar_gid,
+ EC_XWORD(next->ar_size));
if ((strftime(buf,
- DATESIZE,
- "%b %e %H:%M %Y",
+ DATESIZE, MSG_ORIG(MSG_FMT_T_DATE),
localtime(&(next->ar_date)))) == 0) {
- error_message(LOCALTIME_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_LOCALTIME));
exit(1);
}
- (void) fprintf(stdout, " %s ", buf);
+ (void) fprintf(stdout,
+ MSG_ORIG(MSG_FMT_SPSTRSP), buf);
}
if ((next->ar_longname[0] == 0) &&
(next->ar_rawname[0] != 0))
(void) fprintf(stdout,
- "%s\n", trim(next->ar_rawname));
+ MSG_ORIG(MSG_FMT_STRNL),
+ trim(next->ar_rawname));
else
(void) fprintf(stdout,
- "%s\n", trim(next->ar_longname));
+ MSG_ORIG(MSG_FMT_STRNL),
+ trim(next->ar_longname));
}
} /* for */
- return (0);
}
-int
+void
qcmd(Cmd_info *cmd_info)
{
ARFILE *fptr;
- if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) {
- error_message(USAGE_05_ERROR,
- PLAIN_ERROR, (char *)0);
+ if (cmd_info->opt_flgs & (a_FLAG | b_FLAG)) {
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_05));
exit(1);
}
for (fptr = getfile(cmd_info); fptr; fptr = getfile(cmd_info))
;
cleanup(cmd_info);
- return (0);
}
/*
@@ -607,10 +561,11 @@ cleanup(Cmd_info *cmd_info)
*/
mesg('a', cmd_info->namv[i], cmd_info);
f = stats(cmd_info->namv[i], &stbuf);
- if (f == NULL)
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno), cmd_info->namv[i]);
- else {
+ if (f == NULL) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ cmd_info->namv[i], strerror(err));
+ } else {
fileptr = newfile();
/* if short name */
(void) strncpy(fileptr->ar_name,
@@ -619,8 +574,9 @@ cleanup(Cmd_info *cmd_info)
if ((fileptr->ar_longname =
malloc(strlen(trim(cmd_info->namv[i])) + 1)) ==
NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
@@ -629,8 +585,9 @@ cleanup(Cmd_info *cmd_info)
if ((fileptr->ar_pathname =
malloc(strlen(cmd_info->namv[i]) + 1)) == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
@@ -639,43 +596,15 @@ cleanup(Cmd_info *cmd_info)
movefil(fileptr, &stbuf);
/* clear 'ar_flag' */
- fileptr->ar_flag &= ~(F_ELFRAW | F_MMAPED | F_MALLOCED);
-
- if ((cmd_info->OPT_flgs & M_FLAG) == 0) {
- if ((cmd_info->bytes_in_mem + stbuf.st_size) <
- AR_MAX_BYTES_IN_MEM) {
- fileptr->ar_flag &=
- ~(F_ELFRAW | F_MMAPED);
- fileptr->ar_flag |= F_MALLOCED;
- if ((fileptr->ar_contents =
- malloc(ROUNDUP(stbuf.st_size))) ==
- NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- if (fread(fileptr->ar_contents,
- sizeof (char), stbuf.st_size,
- f) != stbuf.st_size) {
- error_message(SYS_READ_ERROR,
- SYSTEM_ERROR,
- strerror(errno),
- fileptr->ar_longname);
- exit(1);
- }
- cmd_info->bytes_in_mem += stbuf.st_size;
- }
- } else {
- fileptr->ar_flag &= ~(F_ELFRAW | F_MALLOCED);
- fileptr->ar_flag |= F_MMAPED;
- if ((fileptr->ar_contents =
- (char *)mmap(0, stbuf.st_size, PROT_READ,
- MAP_SHARED, fileno(f), 0)) == (char *)-1) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- }
+ fileptr->ar_flag &= ~F_ELFRAW;
+
+ /*
+ * Defer reading contents until needed, and then use
+ * an in-kernel file-to-file transfer to avoid
+ * excessive in-process memory use.
+ */
+ fileptr->ar_contents = NULL;
+
(void) fclose(f);
(cmd_info->modified)++;
cmd_info->namv[i] = 0;
@@ -719,7 +648,7 @@ stats(char *file, struct stat *stbuf)
{
FILE *f;
- f = fopen(file, "r");
+ f = fopen(file, MSG_ORIG(MSG_STR_LCR));
if (f == NULL)
return (f);
if (stat(file, stbuf) < 0) {
@@ -747,14 +676,15 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info)
/*
* If -T is specified, check the file length.
*/
- if (cmd_info->OPT_flgs & T_FLAG) {
+ if (cmd_info->opt_flgs & T_FLAG) {
int len;
len = strlen(f_name);
if (f_len <= len) {
dup = malloc(f_len+1);
if (dup == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
(void) strncpy(dup, f_name, f_len);
@@ -782,11 +712,11 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info)
/*
* If -C is specified, this is an error anyway
*/
- if (cmd_info->OPT_flgs & C_FLAG) {
+ if (cmd_info->opt_flgs & C_FLAG) {
+ (void) fprintf(stderr, MSG_INTL(MSG_OVERRIDE_WARN),
+ f_name);
if (dup != NULL)
free(dup);
- error_message(OVERRIDE_WARN_ERROR,
- PLAIN_ERROR, (char *)0, f_name);
return (-1);
}
@@ -802,10 +732,10 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info)
if ((s1.st_dev == s2.st_dev) &&
(s1.st_ino == s2.st_ino)) {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_OVERRIDE_WARN), f_name);
if (dup != NULL)
free(dup);
- error_message(OVERRIDE_WARN_ERROR,
- PLAIN_ERROR, (char *)0, f_name);
return (-1);
}
}
@@ -816,8 +746,9 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info)
*/
f = creat(f_name, (mode_t)a->ar_mode & 0777);
if (f < 0) {
- error_message(SYS_CREATE_01_ERROR,
- SYSTEM_ERROR, strerror(errno), f_name);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), f_name,
+ strerror(err));
/*
* Created
*/
@@ -850,9 +781,9 @@ mesg(int c, char *file, Cmd_info *cmd_info)
*/
if (c == 'u')
c = 'c';
- if (opt_FLAG(cmd_info, v_FLAG))
+ if (cmd_info->opt_flgs & v_FLAG)
if (c != 'c')
- (void) fprintf(stdout, "%c - %s\n", c, file);
+ (void) fprintf(stdout, MSG_ORIG(MSG_FMT_FILE), c, file);
}
static void
diff --git a/usr/src/cmd/sgs/ar/common/file.c b/usr/src/cmd/sgs/ar/common/file.c
index 7457d2e39f..0c48b9f622 100644
--- a/usr/src/cmd/sgs/ar/common/file.c
+++ b/usr/src/cmd/sgs/ar/common/file.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -29,26 +29,57 @@
*
*/
-#include "gelf.h"
+#include <sys/sendfile.h>
#include "inc.h"
-#include "extern.h"
+#include "gelf.h"
+
+/*
+ * List of archive members, accessed globally by cmd and file.
+ */
+ARFILE *listhead, *listend;
+
+/*
+ * Type used to manage string tables. Archives can have two of these:
+ *
+ * sym_strtbl: String table included at the end of the symbol table
+ * archive member, following the offset array.
+ *
+ * long_strtbl: String table used to hold member names that exceed 15
+ * characters in length, found in the long names archive member.
+ */
+typedef struct {
+ char *base; /* Base of string table memory */
+ size_t used; /* # bytes used from allocation */
+ size_t size; /* Size of allocation */
+} ARSTRTBL;
-static char *str_base; /* start of string table for names */
-static char *str_top; /* pointer to next available location */
-static char *str_base1, *str_top1;
-static int pad_symtab; /* # of bytes by which to pad symbol table */
+static ARSTRTBL sym_strtbl;
+static ARSTRTBL long_strtbl;
/*
+ * Name and file descriptor used when creating a new archive.
+ * If this variable references an open file when exit_cleanup()
+ * executes, it will close and remove the file, preventing incomplete
+ * temporary files from being left behind in the case of a failure
+ * or interruption.
+ */
+static struct {
+ int fd; /* -1, or open file descriptor */
+ const char *path; /* Path to open file */
+} ar_outfile;
+
+/*
* The ar file format requires objects to be padded to an even size.
* We do that, but it turns out to be beneficial to go farther.
*
* ld(1) accesses archives by mmapping them into memory. If the mapped
- * objects have the proper alignment, we can access them directly. If the
- * alignment is wrong, libelf "slides" them so that they are also accessible.
- * This is expensive in time (to copy memory) and space (it causes swap
- * to be allocated by the system to back the now-modified pages). Hence, we
- * really want to ensure that the alignment is right.
+ * objects (member data) have the proper alignment, we can access them
+ * directly. If the data alignment is wrong, libelf "slides" them over the
+ * archive header to correct the misalignment. This is expensive in time
+ * (to copy memory) and space (it causes swap to be allocated by the system
+ * to back the now-modified pages). Hence, we really want to ensure that
+ * the alignment is right.
*
* We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects
* at 8-byte. More recently, an elf section type has appeared that has
@@ -67,28 +98,42 @@ static int pad_symtab; /* # of bytes by which to pad symbol table */
#define PADSZ 8
/*
- * Function Prototypes
+ * Forward Declarations
*/
-static long mklong_tab(int *);
-static char *trimslash(char *s);
+static void arwrite(const char *, int, const char *, size_t);
+static size_t mklong_tab();
+static size_t mksymtab(const char *, ARFILEP **, int *);
+static const char *make_tmpname(const char *);
+static size_t sizeof_symtbl(size_t, int, size_t);
+static void savelongname(ARFILE *);
+static void savename(char *);
+static int search_sym_tab(const char *, ARFILE *, Elf *,
+ Elf_Scn *, size_t *, ARFILEP **, size_t *);
+static size_t sizeofmembers(size_t);
+static char *sputl32(uint32_t, char *);
+static char *sputl64(uint64_t, char *);
+static void strtbl_pad(ARSTRTBL *, size_t, int);
+static char *trimslash(char *s);
+static void writesymtab(const char *, int fd, size_t, ARFILEP *,
+ size_t);
-static long mksymtab(ARFILEP **, int *);
-static int writesymtab(char *, long, ARFILEP *);
-static void savename(char *);
-static void savelongname(ARFILE *, char *);
-static void sputl(long, char *);
-
-static char *writelargefile(Cmd_info *cmd_info, long long_tab_size,
- int longnames, ARFILEP *symlist, long nsyms, int found_obj,
- int new_archive);
-
-static int sizeofmembers();
-static int sizeofnewarchive(int, int);
-
-static int search_sym_tab(ARFILE *, Elf *, Elf_Scn *,
- long *, ARFILEP **, int *);
+/*
+ * Function to be called on exit to clean up incomplete new archive.
+ */
+static void
+exit_cleanup(void)
+{
+ if (ar_outfile.fd != -1) {
+ /* Both of these system calls are Async-Signal-Safe */
+ (void) close(ar_outfile.fd);
+ (void) unlink(ar_outfile.path);
+ }
+}
+/*
+ * Open an existing archive.
+ */
int
getaf(Cmd_info *cmd_info)
{
@@ -97,19 +142,21 @@ getaf(Cmd_info *cmd_info)
char *arnam = cmd_info->arnam;
if (elf_version(EV_CURRENT) == EV_NONE) {
- error_message(ELF_VERSION_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_VERSION),
+ elf_errmsg(-1));
exit(1);
}
if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) {
- if (errno == ENOENT) {
+ int err = errno;
+
+ if (err == ENOENT) {
/* archive does not exist yet, may have to create one */
return (fd);
} else {
/* problem other than "does not exist" */
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno), arnam);
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ arnam, strerror(err));
exit(1);
}
}
@@ -118,37 +165,36 @@ getaf(Cmd_info *cmd_info)
cmd_info->arf = elf_begin(fd, cmd, (Elf *)0);
if (elf_kind(cmd_info->arf) != ELF_K_AR) {
- error_message(NOT_ARCHIVE_ERROR,
- PLAIN_ERROR, (char *)0, arnam);
- if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG))
- error_message(USAGE_06_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->ponam);
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_ARCHIVE), arnam);
+ if (cmd_info->opt_flgs & (a_FLAG | b_FLAG))
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_06),
+ cmd_info->ponam);
exit(1);
}
return (fd);
}
/*
- * Given a size, return the number of bytes required to round it
- * up to the next PADSZ boundary.
+ * Given a value, and a pad alignment, return the number of bytes
+ * required to pad the value to the next alignment boundary.
*/
-static int
-pad(int n)
+static size_t
+pad(size_t n, size_t align)
{
- int r;
+ size_t r;
- r = n % PADSZ;
+ r = n % align;
if (r)
- r = PADSZ - r;
+ r = align - r;
return (r);
}
/*
- * If the current archive item is an object, then ar(1) may have added
+ * If the current archive item is an ELF object, then ar(1) may have added
* newline padding at the end in order to bring the following object
* into PADSZ alignment within the file. This padding cannot be
- * distinguished from data using the information kept in the ar headers.
+ * distinguished from data using the information kept in the member header.
* This routine examines the objects, using knowledge of
* ELF and how our tools lay out objects to determine whether padding was
* added to an archive item. If so, it adjusts the st_size and
@@ -157,9 +203,9 @@ pad(int n)
static void
recover_padding(Elf *elf, ARFILE *file)
{
- long extent;
- long padding;
- GElf_Ehdr ehdr;
+ size_t extent;
+ size_t padding;
+ GElf_Ehdr ehdr;
/* ar(1) only pads objects, so bail if not looking at one */
@@ -178,16 +224,24 @@ recover_padding(Elf *elf, ARFILE *file)
*/
extent = gelf_getehdr(elf, &ehdr)
? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0;
- padding = file->ar_size - extent;
- if ((padding < 0) || (padding >= PADSZ)) {
+ /*
+ * If the extent exceeds the end of the archive member
+ * (negative padding), then we don't know what is going on
+ * and simply leave things alone.
+ */
+ if (extent > file->ar_size)
+ return;
+
+ padding = file->ar_size - extent;
+ if (padding >= PADSZ) {
/*
* The section header array is not at the end of the object.
* Traverse the section headers and look for the one with
* the highest used address. If this address is within
* PADSZ bytes of ar_size, then this is the end of the object.
*/
- Elf_Scn *scn = 0;
+ Elf_Scn *scn = NULL;
do {
scn = elf_nextscn(elf, scn);
@@ -195,12 +249,18 @@ recover_padding(Elf *elf, ARFILE *file)
GElf_Shdr shdr;
if (gelf_getshdr(scn, &shdr)) {
- long t = shdr.sh_offset + shdr.sh_size;
+ size_t t;
+
+ t = shdr.sh_offset + shdr.sh_size;
if (t > extent)
extent = t;
}
}
} while (scn);
+
+ if (extent > file->ar_size)
+ return;
+ padding = file->ar_size - extent;
}
/*
@@ -216,9 +276,9 @@ recover_padding(Elf *elf, ARFILE *file)
* characters. If anything else is seen, it is not padding so
* leave it alone.
*/
- if ((padding > 0) && (padding < PADSZ)) {
+ if (padding < PADSZ) {
if (file->ar_contents) {
- long cnt = padding;
+ size_t cnt = padding;
char *p = file->ar_contents + extent;
while (cnt--) {
@@ -235,10 +295,15 @@ recover_padding(Elf *elf, ARFILE *file)
}
}
+/*
+ * Each call to getfile() returns the next unread archive member
+ * from the archive opened by getaf(). Returns NULL if no more
+ * archive members are left.
+ */
ARFILE *
getfile(Cmd_info *cmd_info)
{
- Elf_Arhdr *mem_header;
+ Elf_Arhdr *mem_header = NULL;
ARFILE *file;
char *tmp_rawname, *file_rawname;
Elf *elf;
@@ -249,30 +314,21 @@ getfile(Cmd_info *cmd_info)
if (fd == -1)
return (NULL); /* the archive doesn't exist */
- if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0)
- return (NULL); /* the archive is empty or have hit the end */
-
- if ((mem_header = elf_getarhdr(elf)) == NULL) {
- error_message(ELF_MALARCHIVE_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- arnam, elf_getbase(elf));
- exit(1);
- }
-
- /* zip past special members like the symbol and string table members */
-
- while (strncmp(mem_header->ar_name, "/", 1) == 0 ||
- strncmp(mem_header->ar_name, "//", 2) == 0) {
- (void) elf_next(elf);
- (void) elf_end(elf);
+ while (mem_header == NULL) {
if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0)
- return (NULL);
- /* the archive is empty or have hit the end */
+ return (NULL); /* archive is empty or have hit end */
+
if ((mem_header = elf_getarhdr(elf)) == NULL) {
- error_message(ELF_MALARCHIVE_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- arnam, elf_getbase(elf));
- exit(0);
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_MALARCHIVE),
+ arnam, EC_XWORD(elf_getbase(elf)), elf_errmsg(-1));
+ exit(1);
+ }
+
+ /* Ignore special members like the symbol and string tables */
+ if (mem_header->ar_name[0] == '/') {
+ (void) elf_next(elf);
+ (void) elf_end(elf);
+ mem_header = NULL;
}
}
@@ -288,19 +344,17 @@ getfile(Cmd_info *cmd_info)
file = newfile();
(void) strncpy(file->ar_name, mem_header->ar_name, SNAME);
- if ((file->ar_longname
- = malloc(strlen(mem_header->ar_name) + 1))
+ if ((file->ar_longname = malloc(strlen(mem_header->ar_name) + 1))
== NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
exit(1);
}
(void) strcpy(file->ar_longname, mem_header->ar_name);
- if ((file->ar_rawname
- = malloc(strlen(mem_header->ar_rawname) + 1))
+ if ((file->ar_rawname = malloc(strlen(mem_header->ar_rawname) + 1))
== NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
exit(1);
}
tmp_rawname = mem_header->ar_rawname;
@@ -320,14 +374,14 @@ getfile(Cmd_info *cmd_info)
file->ar_size = mem_header->ar_size;
/* reverse logic */
- if (!(opt_FLAG(cmd_info, t_FLAG) && !opt_FLAG(cmd_info, s_FLAG))) {
+ if ((cmd_info->opt_flgs & (t_FLAG | s_FLAG)) != t_FLAG) {
size_t ptr;
file->ar_flag = F_ELFRAW;
if ((file->ar_contents = elf_rawfile(elf, &ptr))
== NULL) {
if (ptr != 0) {
- error_message(ELF_RAWFILE_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_RAWFILE), elf_errmsg(-1));
exit(1);
}
}
@@ -340,18 +394,22 @@ getfile(Cmd_info *cmd_info)
return (file);
}
+/*
+ * Allocate a new archive member descriptor and add it to the list.
+ */
ARFILE *
newfile(void)
{
static ARFILE *buffer = NULL;
- static int count = 0;
- ARFILE *fileptr;
+ static size_t count = 0;
+ ARFILE *fileptr;
if (count == 0) {
if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE)))
== NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
count = CHUNK;
@@ -374,7 +432,7 @@ trimslash(char *s)
(void) strncpy(buf, trim(s), SNAME - 2);
buf[SNAME - 2] = '\0';
- return (strcat(buf, "/"));
+ return (strcat(buf, MSG_ORIG(MSG_STR_SLASH)));
}
char *
@@ -397,61 +455,91 @@ trim(char *s)
}
-static long
-mksymtab(ARFILEP **symlist, int *found_obj)
+/*
+ * Find all the global symbols exported by ELF archive members, and
+ * build a list associating each one with the archive member that
+ * provides it.
+ *
+ * exit:
+ * *symlist is set to the list of symbols. If any ELF object was
+ * found, *found_obj is set to TRUE (1). Returns the number of symbols
+ * located.
+ */
+static size_t
+mksymtab(const char *arname, ARFILEP **symlist, int *found_obj)
{
- ARFILE *fptr;
- long mem_offset = 0;
- Elf *elf;
- Elf_Scn *scn;
- GElf_Ehdr ehdr;
- int newfd;
- long nsyms = 0;
- int class = 0;
- Elf_Data *data;
- int num_errs = 0;
+ ARFILE *fptr;
+ size_t mem_offset = 0;
+ Elf *elf;
+ Elf_Scn *scn;
+ GElf_Ehdr ehdr;
+ int newfd;
+ size_t nsyms = 0;
+ int class = 0;
+ Elf_Data *data;
+ size_t num_errs = 0;
newfd = 0;
for (fptr = listhead; fptr; fptr = fptr->ar_next) {
/* determine if file is coming from the archive or not */
- if ((fptr->ar_elf != 0) && (fptr->ar_pathname == NULL)) {
+ if ((fptr->ar_elf != NULL) && (fptr->ar_pathname == NULL)) {
/*
* I can use the saved elf descriptor.
*/
elf = fptr->ar_elf;
- } else if ((fptr->ar_elf == 0) &&
+ } else if ((fptr->ar_elf == NULL) &&
(fptr->ar_pathname != NULL)) {
+#ifdef _LP64
+ /*
+ * The archive member header ar_size field is 10
+ * decimal digits, sufficient to represent a 32-bit
+ * value, but not a 64-bit one. Hence, we reject
+ * attempts to insert a member larger than 4GB.
+ *
+ * One obvious way to extend the format without altering
+ * the ar_hdr struct is to use the same mechanism used
+ * for ar_name: Put the size string into the long name
+ * string table and write a string /xxx into ar_size,
+ * where xxx is the string table offset.
+ *
+ * At the time of this writing (June 2010), the largest
+ * relocatable objects are measured in 10s or 100s
+ * of megabytes, so we still have many years to go
+ * before this becomes limiting. By that time, it may
+ * turn out that a completely new archive format is
+ * a better solution, as the current format has many
+ * warts and inefficiencies. In the meantime, we
+ * won't burden the current implementation with support
+ * for a bandaid feature that will have little use.
+ */
+ if (fptr->ar_size > 0xffffffff) {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ERR_MEMBER4G),
+ fptr->ar_pathname);
+ num_errs++;
+ continue;
+ }
+#endif
if ((newfd =
open(fptr->ar_pathname, O_RDONLY)) == -1) {
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno),
- fptr->ar_pathname);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ fptr->ar_pathname, strerror(err));
num_errs++;
continue;
}
if ((elf = elf_begin(newfd,
ELF_C_READ, (Elf *)0)) == 0) {
- if (fptr->ar_pathname != NULL)
- error_message(ELF_BEGIN_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- fptr->ar_pathname);
- else
- error_message(ELF_BEGIN_03_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_BEGIN_FILE),
+ fptr->ar_pathname, elf_errmsg(-1));
(void) close(newfd);
newfd = 0;
num_errs++;
continue;
}
if (elf_kind(elf) == ELF_K_AR) {
- if (fptr->ar_pathname != NULL)
- error_message(ARCHIVE_IN_ARCHIVE_ERROR,
- PLAIN_ERROR, (char *)0,
- fptr->ar_pathname);
- else
- error_message(ARCHIVE_USAGE_ERROR,
- PLAIN_ERROR, (char *)0);
if (newfd) {
(void) close(newfd);
newfd = 0;
@@ -460,8 +548,7 @@ mksymtab(ARFILEP **symlist, int *found_obj)
continue;
}
} else {
- error_message(INTERNAL_01_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01));
exit(1);
}
if (gelf_getehdr(elf, &ehdr) != 0) {
@@ -472,12 +559,14 @@ mksymtab(ARFILEP **symlist, int *found_obj)
scn = elf_getscn(elf, ehdr.e_shstrndx);
if (scn == NULL) {
if (fptr->ar_pathname != NULL)
- error_message(ELF_GETSCN_01_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- fptr->ar_pathname);
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETSCN_FILE),
+ fptr->ar_pathname, elf_errmsg(-1));
else
- error_message(ELF_GETSCN_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETSCN_AR),
+ arname, fptr->ar_longname,
+ elf_errmsg(-1));
num_errs++;
if (newfd) {
(void) close(newfd);
@@ -491,12 +580,14 @@ mksymtab(ARFILEP **symlist, int *found_obj)
data = elf_getdata(scn, data);
if (data == NULL) {
if (fptr->ar_pathname != NULL)
- error_message(ELF_GETDATA_01_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- fptr->ar_pathname);
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETDATA_FILE),
+ fptr->ar_pathname, elf_errmsg(-1));
else
- error_message(ELF_GETDATA_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETDATA_AR),
+ arname, fptr->ar_longname,
+ elf_errmsg(-1));
num_errs++;
if (newfd) {
(void) close(newfd);
@@ -507,12 +598,13 @@ mksymtab(ARFILEP **symlist, int *found_obj)
}
if (data->d_size == 0) {
if (fptr->ar_pathname != NULL)
- error_message(W_ELF_NO_DATA_01_ERROR,
- PLAIN_ERROR, (char *)0,
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_W_ELF_NODATA_FILE),
fptr->ar_pathname);
else
- error_message(W_ELF_NO_DATA_02_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_W_ELF_NODATA_AR),
+ arname, fptr->ar_longname);
if (newfd) {
(void) close(newfd);
newfd = 0;
@@ -527,17 +619,18 @@ mksymtab(ARFILEP **symlist, int *found_obj)
while ((scn = elf_nextscn(elf, scn)) != 0) {
GElf_Shdr shdr;
if (gelf_getshdr(scn, &shdr) == NULL) {
+ /* BEGIN CSTYLED */
if (fptr->ar_pathname != NULL)
- error_message(
- ELF_GETDATA_01_ERROR,
- LIBELF_ERROR,
- elf_errmsg(-1),
- fptr->ar_pathname);
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETDATA_FILE),
+ fptr->ar_pathname,
+ elf_errmsg(-1));
else
- error_message(
- ELF_GETDATA_02_ERROR,
- LIBELF_ERROR,
- elf_errmsg(-1));
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETDATA_AR),
+ arname, fptr->ar_longname,
+ elf_errmsg(-1));
+ /* END CSTYLED */
if (newfd) {
(void) close(newfd);
newfd = 0;
@@ -548,7 +641,7 @@ mksymtab(ARFILEP **symlist, int *found_obj)
}
*found_obj = 1;
if (shdr.sh_type == SHT_SYMTAB)
- if (search_sym_tab(fptr, elf,
+ if (search_sym_tab(arname, fptr, elf,
scn, &nsyms, symlist,
&num_errs) == -1) {
if (newfd) {
@@ -567,448 +660,736 @@ mksymtab(ARFILEP **symlist, int *found_obj)
(void) close(newfd);
newfd = 0;
}
- } /* for */
+ }
if (num_errs)
exit(1);
+
+ if (found_obj) {
+ if (nsyms == 0) {
+ /*
+ * It is possible, though rare, to have ELF objects
+ * that do not export any global symbols. Presumably
+ * such objects operate via their .init/.fini
+ * sections. In this case, we produce an empty
+ * symbol table, so that applications that rely
+ * on a successful call to elf_getarsym() to determine
+ * if ELF objects are present will succeed. To do this,
+ * we require a small empty symbol string table.
+ */
+ strtbl_pad(&sym_strtbl, 4, '\0');
+ } else {
+ /*
+ * Historical behavior is to pad string tables
+ * to a multiple of 4.
+ */
+ strtbl_pad(&sym_strtbl, pad(sym_strtbl.used, 4), '\0');
+ }
+
+ }
+
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().
+ * Output a member header.
*/
-static int
-writesymtab(char *dst, long nsyms, ARFILEP *symlist)
+/*ARGSUSED*/
+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)
{
- char buf1[sizeof (struct ar_hdr) + 1];
- char *buf2, *bptr;
- int i, j;
- ARFILEP *ptr;
- long sym_tab_size = 0;
- int sum = 0;
+ char buf[sizeof (struct ar_hdr) + 1];
+ int len;
+
+ len = snprintf(buf, sizeof (buf), MSG_ORIG(MSG_MH_FORMAT), name,
+ EC_WORD(timestamp), EC_WORD(uid), EC_WORD(gid), EC_WORD(mode),
+ EC_XWORD(size), ARFMAG);
/*
- * patch up archive pointers and write the symbol entries
+ * If snprintf() reports that it needed more space than we gave
+ * it, it means that the caller fed us a long name, which is a
+ * fatal internal error.
*/
- while ((str_top - str_base) & 03) /* round up string table */
- *str_top++ = '\0';
- sym_tab_size = (nsyms +1) * 4 + sizeof (char) * (str_top - str_base);
- if (nsyms == 0)
- sym_tab_size += 4;
- sym_tab_size += pad_symtab;
-
- (void) sprintf(buf1, FORMAT, SYMDIRNAME, time(0), (unsigned)0,
- (unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG);
-
- if (strlen(buf1) != sizeof (struct ar_hdr)) {
- error_message(INTERNAL_02_ERROR);
+ if (len != sizeof (struct ar_hdr)) {
+ (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_02));
exit(1);
}
- if ((buf2 = malloc(4 * (nsyms + 1))) == NULL) {
- error_message(MALLOC_ERROR);
- error_message(DIAG_01_ERROR, errno);
+ arwrite(filename, fd, buf, len);
+
+ /*
+ * We inject inter-member padding to ensure that ELF object
+ * member data is aligned on PADSZ. If this is a debug build,
+ * verify that the computations were right.
+ */
+ assert(!is_elf || (pad(lseek(fd, 0, SEEK_CUR), PADSZ) == 0));
+}
+
+/*
+ * Write the archive symbol table member to the output archive file.
+ *
+ * note:
+ * sizeofmembers() must have been called to establish member offset
+ * and padding values before writesymtab() is used.
+ */
+static void
+writesymtab(const char *filename, int fd, size_t nsyms, ARFILEP *symlist,
+ size_t eltsize)
+{
+ size_t i, j;
+ ARFILEP *ptr;
+ size_t tblsize;
+ char *buf, *dst;
+ int is64 = (eltsize == 8);
+
+ /*
+ * We require a buffer large enough to hold a symbol table count,
+ * plus one offset for each symbol.
+ */
+ tblsize = (nsyms + 1) * eltsize;
+ if ((buf = dst = malloc(tblsize)) == NULL) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
exit(1);
}
- sputl(nsyms, buf2);
- bptr = buf2 + 4;
+
+ write_member_header(filename, fd, 0,
+ (is64 ? MSG_ORIG(MSG_STR_SYM64) : MSG_ORIG(MSG_STR_SLASH)),
+ time(0), 0, 0, 0, tblsize + sym_strtbl.used);
+
+ dst = is64 ? sputl64(nsyms, dst) : sputl32(nsyms, dst);
for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) {
if (!j) {
j = SYMCHUNK;
ptr = (ARFILEP *)*ptr;
}
- sputl((*ptr)->ar_offset, bptr);
- bptr += 4;
- }
- (void) memcpy(dst, buf1, sizeof (struct ar_hdr));
- dst += sizeof (struct ar_hdr);
- sum += sizeof (struct ar_hdr);
-
- (void) memcpy(dst, buf2, (nsyms + 1) * 4);
- dst += (nsyms + 1)*4;
- sum += (nsyms + 1)*4;
-
- if (nsyms != 0) {
- (void) memcpy(dst, str_base, (str_top - str_base));
- dst += str_top - str_base;
- sum += str_top - str_base;
- } else {
- /*
- * Writing a dummy string table.
- */
- int i;
- for (i = 0; i < 4; i++)
- *dst++ = 0;
- sum += 4;
+ dst = is64 ? sputl64((*ptr)->ar_offset, dst) :
+ sputl32((*ptr)->ar_offset, dst);
}
+ arwrite(filename, fd, buf, tblsize);
+ free(buf);
+ arwrite(filename, fd, sym_strtbl.base, sym_strtbl.used);
+}
+
+/*
+ * Grow the size of the given string table so that there is room
+ * for at least need bytes.
+ *
+ * entry:
+ * strtbl - String table to grow
+ * need - Amount of space required by caller
+ */
+static void
+strtbl_alloc(ARSTRTBL *strtbl, size_t need)
+{
+#define STRTBL_INITSZ 8196
+
+ /*
+ * On 32-bit systems, we require a larger integer type in order
+ * to avoid overflow and wraparound when doing our computations.
+ */
+ uint64_t need64 = need;
+ uint64_t used64 = strtbl->used;
+ uint64_t size64 = strtbl->size;
+ uint64_t target = need64 + used64;
+
+ int sys32, tbl32;
+
+ if (target <= size64)
+ return;
+
+ /*
+ * Detect 32-bit system. We might usually do this with the preprocessor,
+ * but it can serve as a predicate in tests that also apply to 64-bit
+ * systems.
+ */
+ sys32 = (sizeof (size_t) == 4);
+
+ /*
+ * The symbol string table can be larger than 32-bits on a 64-bit
+ * system. However, the long name table must stay below that limit.
+ * The reason for this is that there is not enough room in the ar_name
+ * field of the member header to represent 64-bit offsets.
+ */
+ tbl32 = (strtbl == &long_strtbl);
/*
- * The first member file is an ELF object. We need to make
- * sure it will be placed at the PADSZ byte boundary.
+ * If request is larger than 4GB and we can't do it because we
+ * are a 32-bit program, or because the table is format limited,
+ * we can go no further.
*/
- if (pad_symtab) {
- int i;
- for (i = 0; i < pad_symtab; i++)
- *dst++ = 0;
- sum += pad_symtab;
+ if ((target > 0xffffffff) && (sys32 || tbl32))
+ goto limit_fail;
+
+ /* Default starting size */
+ if (strtbl->base == NULL)
+ size64 = STRTBL_INITSZ;
+
+ /*
+ * Our strategy is to double the size until we find a size that
+ * exceeds the request. However, if this table cannot exceed 4GB,
+ * then once we exceed 2GB, we switch to a strategy of taking the
+ * current request and rounding it up to STRTBL_INITSZ.
+ */
+ while (target > size64) {
+ if ((target > 0x7fffffff) && (sys32 || tbl32)) {
+ size64 = ((target + STRTBL_INITSZ) / STRTBL_INITSZ) *
+ STRTBL_INITSZ;
+
+ /*
+ * If we are so close to the line that this small
+ * increment exceeds 4GB, give it up.
+ */
+ if ((size64 > 0xffffffff) && (sys32 || tbl32))
+ goto limit_fail;
+
+ break;
+ }
+
+ size64 *= 2;
}
- free(buf2);
- return (sum);
+ strtbl->base = realloc(strtbl->base, size64);
+ if (strtbl->base == NULL) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
+ exit(1);
+ }
+ strtbl->size = (size_t)size64;
+ return;
+
+limit_fail:
+ /*
+ * Control comes here if we are unable to allocate more than 4GB of
+ * memory for the string table due to one of the following reasons:
+ *
+ * - A 32-bit process is attempting to be larger than 4GB
+ *
+ * - A 64-bit process is attempting to grow the long names string
+ * table beyond the ar format limit of 32-bits.
+ */
+ if (sys32)
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
+ else
+ (void) fprintf(stderr, MSG_INTL(MSG_ERR_LONGSTRTBLSZ));
+ exit(1);
+
+#undef STRTBL_INITSZ
}
+/*
+ * Add the specified number of pad characters to the end of the
+ * given string table.
+ *
+ * entry:
+ * strtbl - String table to pad
+ * n - # of pad characters to add
+ * ch - Pad character to use
+ */
static void
-savename(char *symbol)
+strtbl_pad(ARSTRTBL *strtbl, size_t n, int ch)
{
- static int str_length = BUFSIZ * 5;
- char *p, *s;
- unsigned int i;
- int diff;
-
- diff = 0;
- if (str_base == (char *)0) {
- /* no space allocated yet */
- if ((str_base = malloc((unsigned)str_length)) == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- str_top = str_base;
- }
+ if (n == 0)
+ return;
- p = str_top;
- str_top += strlen(symbol) + 1;
+ if ((n + strtbl->used) > strtbl->size)
+ strtbl_alloc(strtbl, n);
- if (str_top > str_base + str_length) {
- char *old_base = str_base;
+ while (n--)
+ strtbl->base[strtbl->used++] = ch;
+}
- do
- str_length += BUFSIZ * 2;
- while (str_top > str_base + str_length)
- ;
- if ((str_base = (char *)realloc(str_base, str_length)) ==
- NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- /*
- * Re-adjust other pointers
- */
- diff = str_base - old_base;
- p += diff;
- }
- for (i = 0, s = symbol; i < strlen(symbol) && *s != '\0'; i++) {
- *p++ = *s++;
- }
- *p++ = '\0';
- str_top = p;
+/*
+ * Enter a symbol name into the symbol string table.
+ */
+static void
+savename(char *symbol)
+{
+ size_t need;
+
+ need = strlen(symbol) + 1;
+ if ((need + sym_strtbl.used) > sym_strtbl.size)
+ strtbl_alloc(&sym_strtbl, need);
+
+ (void) strcpy(sym_strtbl.base + sym_strtbl.used, symbol);
+ sym_strtbl.used += need;
}
+/*
+ * Prepare an archive member with a long (>15 characters) name for
+ * the output archive.
+ *
+ * entry:
+ * fptr - pointer to archive member with long name
+ *
+ * exit:
+ * The long name is entered into the long name string table,
+ * and fptr->ar_name has been replaced with the special /xxx
+ * name used to indicate that the real name is in the string table
+ * at offset xxx.
+ */
static void
-savelongname(ARFILE *fptr, char *ptr_index)
+savelongname(ARFILE *fptr)
{
- static int str_length = BUFSIZ * 5;
- char *p, *s;
- unsigned int i;
- int diff;
- static int bytes_used;
- int index;
- char ptr_index1[SNAME-1];
-
- diff = 0;
- if (str_base1 == (char *)0) {
- /* no space allocated yet */
- if ((str_base1 = malloc((unsigned)str_length))
- == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- str_top1 = str_base1;
- }
+ size_t len, need;
+ char *p;
- p = str_top1;
- str_top1 += strlen(fptr->ar_longname) + 2;
-
- index = bytes_used;
- (void) sprintf(ptr_index1, "%d", index); /* holds digits */
- (void) sprintf(ptr_index, FNFORMAT, SYMDIRNAME);
- ptr_index[1] = '\0';
- (void) strcat(ptr_index, ptr_index1);
- (void) strcpy(fptr->ar_name, ptr_index);
- bytes_used += strlen(fptr->ar_longname) + 2;
-
- if (str_top1 > str_base1 + str_length) {
- char *old_base = str_base1;
-
- do
- str_length += BUFSIZ * 2;
- while (str_top1 > str_base1 + str_length)
- ;
- if ((str_base1 = (char *)realloc(str_base1, str_length))
- == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- /*
- * Re-adjust other pointers
- */
- diff = str_base1 - old_base;
- p += diff;
- }
- for (i = 0, s = fptr->ar_longname;
- i < strlen(fptr->ar_longname) && *s != '\0'; i++) {
- *p++ = *s++;
- }
+ /* Size of new item to add */
+ len = strlen(fptr->ar_longname);
+ need = len + 2;
+
+ /* Ensure there's room */
+ if ((need + long_strtbl.used) > long_strtbl.size)
+ strtbl_alloc(&long_strtbl, need);
+
+ /*
+ * Generate the index string to be written into the member header
+ *
+ * This will not overflow the ar_name field because that field is
+ * 16 characters in size, and a 32-bit unsigned value can be formatted
+ * in 10 characters. Allowing a character for the leading '/', and one
+ * for the NULL termination, that leaves us with 4 extra spaces.
+ */
+ (void) snprintf(fptr->ar_name, sizeof (fptr->ar_name),
+ MSG_ORIG(MSG_FMT_LLINT), EC_XWORD(long_strtbl.used));
+
+ /*
+ * Enter long name into reserved spot, terminated with a slash
+ * and a newline character.
+ */
+ p = long_strtbl.base + long_strtbl.used;
+ long_strtbl.used += need;
+ (void) strcpy(p, fptr->ar_longname);
+ p += len;
*p++ = '/';
*p++ = '\n';
- str_top1 = p;
}
-char *
+/*
+ * Determine if the archive we're about to write will exceed the
+ * 32-bit limit of 4GB.
+ *
+ * entry:
+ * mksymtab() and mklong_tab() have been called to set up
+ * the string tables.
+ *
+ * exit:
+ * Returns TRUE (1) if the 64-bit symbol table is needed, and
+ * FALSE (0) otherwise.
+ *
+ */
+static int
+require64(size_t nsyms, int found_obj, size_t longnames)
+{
+ ARFILE *fptr;
+ uint64_t size;
+
+ /*
+ * If there are more than 4GB symbols, we have to use
+ * the 64-bit form. Note that longnames cannot exceed 4GB
+ * because that symbol table is limited to a length of 4GB by
+ * the archive format.
+ */
+ if (nsyms > 0xffffffff)
+ return (1);
+
+ /*
+ * Make a worst case estimate for the size of the resulting
+ * archive by assuming full padding between members.
+ */
+ size = SARMAG;
+ if (longnames)
+ size += sizeof (struct ar_hdr) + long_strtbl.used + PADSZ;
+
+ if (found_obj)
+ size += sizeof_symtbl(nsyms, found_obj, 4) + PADSZ;
+
+ if (size > 0xffffffff)
+ return (1);
+
+ for (fptr = listhead; fptr; fptr = fptr->ar_next) {
+ size += sizeof (struct ar_hdr) + fptr->ar_size + PADSZ;
+
+ if (size > 0xffffffff)
+ return (1);
+ }
+
+ /* 32-bit symbol table will suffice */
+ return (0);
+}
+
+void
writefile(Cmd_info *cmd_info)
{
- ARFILE * fptr;
- ARFILEP *symlist = 0;
- int i;
- int longnames = 0;
- long long_tab_size = 0;
- long nsyms;
- int new_archive = 0;
- char *name = cmd_info->arnam;
- int arsize;
- char *dst;
- char *tmp_dst;
- int nfd;
- int found_obj = 0;
-
- long_tab_size = mklong_tab(&longnames);
- nsyms = mksymtab(&symlist, &found_obj);
-
- for (i = 0; signum[i]; i++)
- /* started writing, cannot interrupt */
- (void) signal(signum[i], SIG_IGN);
-
-
- /* Is this a new archive? */
- if ((access(cmd_info->arnam, 0) < 0) && (errno == ENOENT)) {
- new_archive = 1;
- if (!opt_FLAG(cmd_info, c_FLAG)) {
- error_message(BER_MES_CREATE_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->arnam);
+ ARFILE *fptr;
+ ARFILEP *symlist = 0;
+ size_t longnames;
+ size_t nsyms;
+ int new_archive = 0;
+ char *name = cmd_info->arnam;
+ size_t arsize; /* Size of magic # and special members */
+ size_t symtbl_eltsize = 4;
+ int found_obj = 0;
+ int fd;
+ off_t off;
+ struct stat stbuf, ar_stbuf;
+ char pad_bytes[PADSZ];
+ size_t pad_cnt;
+ int is_elf;
+
+ /*
+ * Gather the list of symbols and associate each one to the
+ * ARFILE descriptor of the object it belongs to. At the same
+ * time, tag each ELF object with the appropriate F_CLASSxx
+ * flag.
+ */
+ nsyms = mksymtab(name, &symlist, &found_obj);
+
+ /* Generate the string table for long member names */
+ longnames = mklong_tab();
+
+ /*
+ * Will this archive exceed 4GB? If we're a 32-bit process, we can't
+ * do it. If we're a 64-bit process, then we'll have to use a
+ * 64-bit symbol table.
+ */
+ if (require64(nsyms, found_obj, longnames)) {
+#ifdef _LP64
+ symtbl_eltsize = 8;
+#else
+ (void) fprintf(stderr, MSG_INTL(MSG_TOOBIG4G));
+ exit(1);
+#endif
+ }
+
+ /*
+ * If the user requested it, use the 64-bit symbol table even if
+ * a 32-bit one would suffice. 32-bit tables are more portable and
+ * take up less room, so this feature is primarily for testing.
+ */
+ if (cmd_info->opt_flgs & S_FLAG)
+ symtbl_eltsize = 8;
+
+ /*
+ * If the first non-special archive member is an ELF object, then we
+ * need to arrange for its data to have an alignment of PADSZ. The
+ * preceeding special member will be the symbol table, or the long
+ * name string table. We pad the string table that precedes the
+ * ELF member in order to achive the desired alignment.
+ */
+ is_elf = listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64));
+ arsize = SARMAG;
+ if (found_obj) {
+ arsize += sizeof_symtbl(nsyms, found_obj, symtbl_eltsize);
+ if (is_elf && (longnames == 0)) {
+ pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
+ strtbl_pad(&sym_strtbl, pad_cnt, '\0');
+ arsize += pad_cnt;
}
- } else
- new_archive = 0;
+ }
+ if (longnames > 0) {
+ arsize += sizeof (struct ar_hdr) + long_strtbl.used;
+ if (is_elf) {
+ pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ);
+ strtbl_pad(&long_strtbl, pad_cnt, '\0');
+ arsize += pad_cnt;
+ }
+ }
/*
- * Calculate the size of the new archive
+ * For each user visible (non-special) archive member, determine
+ * the header offset, and the size of any required padding.
*/
- arsize = sizeofnewarchive(nsyms, longnames);
+ (void) sizeofmembers(arsize);
/*
- * Dummy symtab ?
+ * Is this a new archive, or are we updating an existing one?
+ *
+ * A subtlety here is that POSIX says we are not supposed
+ * to replace a non-writable file. The only 100% reliable test
+ * against this is to open the file for non-destructive
+ * write access. If the open succeeds, we are clear to
+ * replace it, and if not, then the error generated is
+ * the error we need to report.
*/
- if (nsyms == 0 && found_obj != 0)
- /*
- * 4 + 4 = First 4 bytes to keep the number of symbols.
- * The second 4 bytes for string table.
- */
- arsize += sizeof (struct ar_hdr) + 4 + 4;
+ if ((fd = open(name, O_RDWR)) < 0) {
+ int err = errno;
- if (arsize > AR_MAX_BYTES_IN_MEM) {
- tmp_dst = dst = NULL;
+ if (err != ENOENT) {
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ name, strerror(err));
+ exit(1);
+ }
+ new_archive = 1;
+ if ((cmd_info->opt_flgs & c_FLAG) == 0) {
+ (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_CREATE),
+ cmd_info->arnam);
+ }
} else {
- tmp_dst = dst = malloc(arsize);
- }
- if (dst == NULL) {
- return writelargefile(cmd_info, long_tab_size,
- longnames, symlist, nsyms, found_obj, new_archive);
+ /* Capture mode and owner information to apply to replacement */
+ if (fstat(fd, &ar_stbuf) < 0) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT),
+ name, strerror(err));
+ (void) close(fd);
+ exit(1);
+ }
+ (void) close(fd);
+ new_archive = 0;
}
- (void) memcpy(tmp_dst, ARMAG, SARMAG);
- tmp_dst += SARMAG;
- if (nsyms || found_obj != 0) {
- int diff;
- diff = writesymtab(tmp_dst, nsyms, symlist);
- tmp_dst += diff;
+ /*
+ * Register exit handler function to clean up after us if we exit
+ * before completing the new archive. atexit() is defined as
+ * only being able to fail due to memory exhaustion.
+ */
+ if (atexit(exit_cleanup) != 0) {
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM));
+ exit(1);
+ }
+
+ /*
+ * If a new archive, create it in place. If updating an archive,
+ * create the replacement under a temporary name and then rename it
+ * into place.
+ */
+ ar_outfile.path = new_archive ? name : make_tmpname(name);
+ ar_outfile.fd = open(ar_outfile.path, O_RDWR|O_CREAT|O_LARGEFILE, 0666);
+ if (ar_outfile.fd == -1) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ ar_outfile.path, strerror(err));
+ exit(1);
}
+ /* Output magic string */
+ arwrite(name, ar_outfile.fd, ARMAG, SARMAG);
+
+ /*
+ * The symbol table member is always first if present. Note that
+ * writesymtab() uses the member offsets computed by sizeofmembers()
+ * above.
+ */
+ if (found_obj)
+ writesymtab(name, ar_outfile.fd, nsyms, symlist,
+ symtbl_eltsize);
+
if (longnames) {
- (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0),
- (unsigned)0, (unsigned)0, (unsigned)0,
- (long)long_tab_size, ARFMAG);
- tmp_dst += sizeof (struct ar_hdr);
- (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1);
- tmp_dst += str_top1 - str_base1;
+ write_member_header(name, ar_outfile.fd, 0,
+ MSG_ORIG(MSG_STR_DSLASH), time(0), 0, 0, 0,
+ long_strtbl.used);
+ arwrite(name, ar_outfile.fd, long_strtbl.base,
+ long_strtbl.used);
}
- for (fptr = listhead; fptr; fptr = fptr->ar_next) {
/*
- * 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".
+ * The accuracy of the symbol table depends on our having calculated
+ * the size of the archive accurately to this point. If this is a
+ * debug build, verify it.
*/
+ assert(arsize == lseek(ar_outfile.fd, 0, SEEK_CUR));
+
+#ifndef XPG4
+ if (cmd_info->opt_flgs & v_FLAG) {
+ (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_WRITE),
+ cmd_info->arnam);
+ }
+#endif
+
+ /*
+ * Fill pad_bytes array with newline characters. This array
+ * is used to supply padding bytes at the end of ELF objects.
+ * There can never be more tha PADSZ such bytes, so this number
+ * will always suffice.
+ */
+ for (pad_cnt = 0; pad_cnt < PADSZ; pad_cnt++)
+ pad_bytes[pad_cnt] = '\n';
+
+ for (fptr = listhead; fptr; fptr = fptr->ar_next) {
+ /*
+ * We computed the expected offset for each ELF member and
+ * used those offsets to fill the symbol table. If this is
+ * a debug build, verify that the computed offset was right.
+ */
+ is_elf = (fptr->ar_flag & (F_CLASS32 | F_CLASS64)) != 0;
+ assert(!is_elf ||
+ (fptr->ar_offset == lseek(ar_outfile.fd, 0, SEEK_CUR)));
+
+ /*
+ * 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 (fptr->ar_name[0] == 0) {
fptr->ar_longname = fptr->ar_rawname;
(void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME);
}
- if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2)
- (void) sprintf(tmp_dst, FNFORMAT,
- trimslash(fptr->ar_longname));
- else
- (void) sprintf(tmp_dst, FNFORMAT, fptr->ar_name);
- (void) sprintf(tmp_dst+16, TLFORMAT, fptr->ar_date,
- (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid,
- (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding,
- ARFMAG);
-
- tmp_dst += sizeof (struct ar_hdr);
-
- if (!(fptr->ar_flag & F_MALLOCED) &&
- !(fptr->ar_flag & F_MMAPED) &&
- !(fptr->ar_flag & F_ELFRAW)) {
- /* file was not read in fptr->ar_contents during 'cmd' */
- /* do it now */
- FILE *f;
- f = fopen(fptr->ar_pathname, "r");
- if (f == NULL) {
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno),
- fptr->ar_longname);
+ write_member_header(name, ar_outfile.fd, is_elf,
+ (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) ?
+ trimslash(fptr->ar_longname) : fptr->ar_name,
+ EC_WORD(fptr->ar_date), fptr->ar_uid, fptr->ar_gid,
+ fptr->ar_mode, fptr->ar_size + fptr->ar_padding);
+
+
+ if ((fptr->ar_flag & F_ELFRAW) == 0) {
+ /*
+ * The file doesn't come from the archive, and is
+ * therefore not already in memory(fptr->ar_contents)
+ * so open it and do a direct file-to-file transfer of
+ * its contents. We use the sendfile() system call
+ * to make the kernel do the transfer, so we don't have
+ * to buffer data in process, and we trust that the
+ * kernel will use an optimal transfer strategy.
+ */
+ if ((fd = open(fptr->ar_pathname, O_RDONLY)) == -1) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ fptr->ar_longname, strerror(err));
+ exit(1);
+ }
+ if (stat(fptr->ar_pathname, &stbuf) < 0) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
+ fptr->ar_longname, strerror(err));
+ (void) close(fd);
exit(1);
- } else {
- if (fread(tmp_dst, sizeof (char),
- fptr->ar_size, f) != fptr->ar_size) {
- error_message(SYS_READ_ERROR,
- SYSTEM_ERROR, strerror(errno),
- fptr->ar_longname);
- exit(1);
- }
}
- (void) fclose(f);
+ off = 0;
+ if (sendfile(ar_outfile.fd, fd, &off,
+ stbuf.st_size) != stbuf.st_size) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
+ name, strerror(err));
+ exit(2);
+ }
+ (void) close(fd);
} else {
- (void) memcpy(tmp_dst, fptr->ar_contents,
+ /* Archive member is in memory. Write it out */
+ arwrite(name, ar_outfile.fd, fptr->ar_contents,
fptr->ar_size);
- if (fptr->ar_flag & F_MALLOCED) {
- (void) free(fptr->ar_contents);
- fptr->ar_flag &= ~(F_MALLOCED);
- }
}
- tmp_dst += fptr->ar_size;
- if (fptr->ar_size & 0x1) {
- (void) memcpy(tmp_dst, "\n", 1);
- tmp_dst++;
- }
-
- if (fptr->ar_padding) {
- int i = fptr->ar_padding;
- while (i) {
- *tmp_dst++ = '\n';
- --i;
- }
- }
+ /*
+ * All archive members are padded to at least a boundary of 2.
+ * The expression ((fptr->ar_size & 0x1) != 0) yields 1 for
+ * odd boundaries, and 0 for even ones. To this, we add
+ * whatever padding is needed for ELF objects.
+ */
+ pad_cnt = ((fptr->ar_size & 0x1) != 0) + fptr->ar_padding;
+ if (pad_cnt > 0)
+ arwrite(name, ar_outfile.fd, pad_bytes, pad_cnt);
}
/*
- * All preparation for writing is done.
+ * All archive output is done.
*/
+ if (close(ar_outfile.fd) < 0) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_CLOSE), ar_outfile.path,
+ strerror(err));
+ exit(1);
+ }
+ ar_outfile.fd = -1; /* Prevent removal on exit */
(void) elf_end(cmd_info->arf);
(void) close(cmd_info->afd);
/*
- * Write out to the file
+ * If updating an existing archive, rename the new version on
+ * top of the original.
*/
- if (new_archive) {
- /*
- * create a new file
- */
- nfd = creat(name, 0666);
- if (nfd == -1) {
- error_message(SYS_CREATE_01_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
- exit(1);
- }
- } else {
+ if (!new_archive) {
/*
- * Open the new file
+ * Prevent the replacement of the original archive from
+ * being interrupted, to lower the possibility of an
+ * interrupt destroying a pre-existing archive.
*/
- nfd = open(name, O_RDWR|O_TRUNC);
- if (nfd == -1) {
- error_message(SYS_WRITE_02_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
+ establish_sighandler(SIG_IGN);
+
+ if (rename(ar_outfile.path, name) < 0) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_RENAME),
+ ar_outfile.path, name, strerror(err));
+ (void) unlink(ar_outfile.path);
exit(1);
}
+ (void) chmod(name, ar_stbuf.st_mode & 0777);
+ if (chown(name, ar_stbuf.st_uid, ar_stbuf.st_gid) >= 0)
+ (void) chmod(name, ar_stbuf.st_mode & 07777);
+
}
-#ifndef XPG4
- if (opt_FLAG(cmd_info, v_FLAG)) {
- error_message(BER_MES_WRITE_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->arnam);
- }
-#endif
- if (write(nfd, dst, arsize) != arsize) {
- error_message(SYS_WRITE_04_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
- if (!new_archive)
- error_message(WARN_USER_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(2);
- }
- return (dst);
}
-static long
-mklong_tab(int *longnames)
+/*
+ * Examine all the archive members, enter any member names longer than
+ * 15 characters into the long name string table, and count the number
+ * of names found.
+ *
+ * Returns the size of the resulting archive member, including the
+ * member header.
+ */
+static size_t
+mklong_tab(void)
{
ARFILE *fptr;
- char ptr_index[SNAME+1];
- long ret = 0;
+ size_t longnames = 0;
for (fptr = listhead; fptr; fptr = fptr->ar_next) {
if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) {
- (*longnames)++;
- savelongname(fptr, ptr_index);
- (void) strcpy(fptr->ar_name, ptr_index);
+ longnames++;
+ savelongname(fptr);
}
}
- if (*longnames) {
- /* round up table that keeps the long filenames */
- while ((str_top1 - str_base1) & 03)
- *str_top1++ = '\n';
- ret = sizeof (char) * (str_top1 - str_base1);
- }
- return (ret);
+
+ /* round up table that keeps the long filenames */
+ if (longnames > 0)
+ strtbl_pad(&long_strtbl, pad(long_strtbl.used, 4), '\n');
+
+ return (longnames);
}
-/* Put bytes in archive header in machine independent order. */
+/*
+ * Write 32/64-bit words into buffer in archive symbol table
+ * standard byte order (MSB).
+ */
+static char *
+sputl32(uint32_t n, char *cp)
+{
+ *cp++ = n >> 24;
+ *cp++ = n >> 16;
+ *cp++ = n >> 8;
-static void
-sputl(long n, char *cp)
+ *cp++ = n & 255;
+
+ return (cp);
+}
+
+static char *
+sputl64(uint64_t n, char *cp)
{
+ *cp++ = n >> 56;
+ *cp++ = n >> 48;
+ *cp++ = n >> 40;
+ *cp++ = n >> 32;
+
*cp++ = n >> 24;
*cp++ = n >> 16;
*cp++ = n >> 8;
*cp++ = n & 255;
+
+ return (cp);
}
static int
-search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
- long *nsyms, ARFILEP **symlist, int *num_errs)
+search_sym_tab(const char *arname, ARFILE *fptr, Elf *elf, Elf_Scn *scn,
+ size_t *nsyms, ARFILEP **symlist, size_t *num_errs)
{
Elf_Data *str_data, *sym_data; /* string table, symbol table */
Elf_Scn *str_scn;
@@ -1026,20 +1407,18 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */
if (str_scn == NULL) {
if (fname != NULL)
- error_message(ELF_GETDATA_01_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- fname);
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
+ fname, elf_errmsg(-1));
else
- error_message(ELF_GETDATA_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
+ arname, fptr->ar_longname, elf_errmsg(-1));
(*num_errs)++;
return (-1);
}
no_of_symbols = shdr.sh_size / shdr.sh_entsize;
if (no_of_symbols == -1) {
- error_message(SYMTAB_01_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_01));
return (-1);
}
@@ -1047,11 +1426,11 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
str_shtype = shdr.sh_type;
if (str_shtype == -1) {
if (fname != NULL)
- error_message(ELF_GETDATA_01_ERROR,
- LIBELF_ERROR, elf_errmsg(-1), fname);
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE),
+ fname, elf_errmsg(-1));
else
- error_message(ELF_GETDATA_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1));
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR),
+ arname, fptr->ar_longname, elf_errmsg(-1));
(*num_errs)++;
return (-1);
}
@@ -1062,45 +1441,40 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
if (str_shtype != SHT_STRTAB) {
if (fname != NULL)
- error_message(SYMTAB_02_ERROR,
- PLAIN_ERROR, (char *)0,
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_FILE),
fname);
else
- error_message(SYMTAB_03_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_AR),
+ arname, fptr->ar_longname);
return (0);
}
str_data = 0;
if ((str_data = elf_getdata(str_scn, str_data)) == 0) {
if (fname != NULL)
- error_message(SYMTAB_04_ERROR,
- PLAIN_ERROR, (char *)0,
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_FILE),
fname);
else
- error_message(SYMTAB_05_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_AR),
+ arname, fptr->ar_longname);
return (0);
}
if (str_data->d_size == 0) {
if (fname != NULL)
- error_message(SYMTAB_06_ERROR,
- PLAIN_ERROR, (char *)0,
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_FILE),
fname);
else
- error_message(SYMTAB_07_ERROR,
- PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_AR),
+ arname, fptr->ar_longname);
return (0);
}
sym_data = 0;
if ((sym_data = elf_getdata(scn, sym_data)) == NULL) {
if (fname != NULL)
- error_message(ELF_01_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_FILE),
fname, elf_errmsg(-1));
else
- error_message(ELF_02_ERROR,
- LIBELF_ERROR, elf_errmsg(-1),
- elf_errmsg(-1));
+ (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_AR),
+ arname, fptr->ar_longname, elf_errmsg(-1));
return (0);
}
@@ -1118,8 +1492,10 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
sym_ptr = malloc((SYMCHUNK+1)
* sizeof (ARFILEP));
if (sym_ptr == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
syms_left = SYMCHUNK;
@@ -1144,12 +1520,12 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn,
/*
* Get the output file size
*/
-static int
-sizeofmembers(int psum)
+static size_t
+sizeofmembers(size_t psum)
{
- int sum = 0;
- ARFILE *fptr;
- int hdrsize = sizeof (struct ar_hdr);
+ size_t sum = 0;
+ ARFILE *fptr;
+ size_t hdrsize = sizeof (struct ar_hdr);
for (fptr = listhead; fptr; fptr = fptr->ar_next) {
fptr->ar_offset = psum + sum;
@@ -1161,7 +1537,7 @@ sizeofmembers(int psum)
/*
* If the current item, and the next item are both ELF
* objects, then add padding to current item so that the
- * next item will have PADSZ alignment.
+ * data in the next item will have PADSZ alignment.
*
* In any other case, set the padding to 0. If the
* item comes from another archive, it may be carrying
@@ -1171,7 +1547,7 @@ sizeofmembers(int psum)
if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) &&
fptr->ar_next &&
(fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) {
- fptr->ar_padding = pad(psum + sum + hdrsize);
+ fptr->ar_padding = pad(psum + sum + hdrsize, PADSZ);
sum += fptr->ar_padding;
} else {
fptr->ar_padding = 0;
@@ -1180,292 +1556,63 @@ sizeofmembers(int psum)
return (sum);
}
-static int
-sizeofnewarchiveheader(int nsyms, int longnames)
+/*
+ * Compute the size of the symbol table archive member.
+ *
+ * entry:
+ * nsyms - # of symbols in the table
+ * found_obj - TRUE if the archive contains any ELF objects
+ * eltsize - Size of the integer type to use for the symbol
+ * table. 4 for 32-bit tables, and 8 for 64-bit tables.
+ */
+static size_t
+sizeof_symtbl(size_t nsyms, int found_obj, size_t eltsize)
{
- int sum = 0;
-
- sum += SARMAG;
+ size_t sum = 0;
- if (nsyms) {
- char *top = (char *)str_top;
- char *base = (char *)str_base;
-
- while ((top - base) & 03)
- top++;
- sum += sizeof (struct ar_hdr);
- sum += (nsyms + 1) * 4;
- sum += top - base;
+ if (found_obj) {
+ /* Member header, symbol count, and one slot per symbol */
+ sum += sizeof (struct ar_hdr) + ((nsyms + 1) * eltsize);
+ sum += sym_strtbl.used;
}
- if (longnames) {
- sum += sizeof (struct ar_hdr);
- sum += str_top1 - str_base1;
- }
-
- /*
- * If the first member file is an ELF object,
- * we have to ensure the member contents will align
- * on PADSZ byte boundary.
- */
- if (listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64))) {
- pad_symtab = pad(sum + sizeof (struct ar_hdr));
- sum += pad_symtab;
- }
-
- return (sum);
-}
-
-static int
-sizeofnewarchive(int nsyms, int longnames)
-{
- int sum;
-
- sum = sizeofnewarchiveheader(nsyms, longnames);
- sum += sizeofmembers(sum);
return (sum);
}
static void
-arwrite(char *name, int nfd, char *dst, int size) {
+arwrite(const char *name, int nfd, const char *dst, size_t size) {
if (write(nfd, dst, size) != size) {
- error_message(SYS_WRITE_04_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE),
+ name, strerror(err));
exit(2);
}
}
-static char *
-make_tmpname(char *filename) {
- static char template[] = "arXXXXXX";
- char *tmpname;
- char *slash = strrchr(filename, '/');
-
- if (slash != (char *)NULL) {
- char c;
-
- c = *slash;
- *slash = 0;
- tmpname = (char *)malloc(strlen(filename) +
- sizeof (template) + 2);
- (void) strcpy(tmpname, filename);
- (void) strcat(tmpname, "/");
- (void) strcat(tmpname, template);
- (void) mktemp(tmpname);
- *slash = c;
- } else {
- tmpname = malloc(sizeof (template));
- (void) strcpy(tmpname, template);
- (void) mktemp(tmpname);
- }
- return (tmpname);
-}
-
-static int
-ar_copy(char *from, char *to) {
- int fromfd, tofd, nread;
- int saved;
- char buf[8192];
-
- fromfd = open(from, O_RDONLY);
- if (fromfd < 0)
- return (-1);
- tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 0777);
- if (tofd < 0) {
- saved = errno;
- (void) close(fromfd);
- errno = saved;
- return (-1);
- }
- while ((nread = read(fromfd, buf, sizeof (buf))) > 0) {
- if (write(tofd, buf, nread) != nread) {
- saved = errno;
- (void) close(fromfd);
- (void) close(tofd);
- errno = saved;
- return (-1);
- }
- }
- saved = errno;
- (void) close(fromfd);
- (void) close(tofd);
- if (nread < 0) {
- errno = saved;
- return (-1);
- }
- return (0);
-}
-
-static int
-ar_rename(char *from, char *to)
-{
- int exists;
- struct stat s;
- int ret = 0;
-
- exists = lstat(to, &s) == 0;
-
- if (! exists || (!S_ISLNK(s.st_mode) && s.st_nlink == 1)) {
- ret = rename(from, to);
- if (ret == 0) {
- if (exists) {
- (void) chmod(to, s.st_mode & 0777);
- if (chown(to, s.st_uid, s.st_gid) >= 0)
- (void) chmod(to, s.st_mode & 07777);
- }
- } else {
- (void) unlink(from);
- }
- } else {
- ret = ar_copy(from, to);
- (void) unlink(from);
- }
- return (ret);
-}
-
-static char *
-writelargefile(Cmd_info *cmd_info, long long_tab_size, int longnames,
- ARFILEP *symlist, long nsyms, int found_obj, int new_archive)
-{
- ARFILE * fptr;
- char *name = cmd_info->arnam;
- int arsize;
- char *dst;
- char *tmp_dst;
- int nfd;
- char *new_name;
- FILE *f;
- struct stat stbuf;
-
- new_name = make_tmpname(name);
-
- if (new_archive) {
- nfd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0666);
- if (nfd == -1) {
- error_message(SYS_CREATE_01_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
- exit(1);
- }
- } else {
- nfd = open(new_name, O_RDWR|O_CREAT|O_LARGEFILE, 0666);
- if (nfd == -1) {
- error_message(SYS_WRITE_02_ERROR,
- SYSTEM_ERROR, strerror(errno), name);
- exit(1);
- }
- }
-
- arsize = sizeofnewarchiveheader(nsyms, longnames);
- if (nsyms == 0 && found_obj != 0)
- arsize += sizeof (struct ar_hdr) + 4 + 4;
- if (arsize < 2048) {
- arsize = 2048;
- }
- dst = tmp_dst = (char *)malloc(arsize);
- (void) memcpy(tmp_dst, ARMAG, SARMAG);
- tmp_dst += SARMAG;
-
- if (nsyms || found_obj != 0) {
- int diff;
- diff = writesymtab(tmp_dst, nsyms, symlist);
- tmp_dst += diff;
- }
-
- if (longnames) {
- (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0),
- (unsigned)0, (unsigned)0, (unsigned)0,
- (long)long_tab_size, ARFMAG);
- tmp_dst += sizeof (struct ar_hdr);
- (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1);
- tmp_dst += str_top1 - str_base1;
- }
-#ifndef XPG4
- if (opt_FLAG(cmd_info, v_FLAG)) {
- error_message(BER_MES_WRITE_ERROR,
- PLAIN_ERROR, (char *)0,
- cmd_info->arnam);
- }
-#endif
- arwrite(name, nfd, dst, (int)(tmp_dst - dst));
-
- for (fptr = listhead; fptr; fptr = fptr->ar_next) {
- if (fptr->ar_name[0] == 0) {
- fptr->ar_longname = fptr->ar_rawname;
- (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME);
- }
- if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2)
- (void) sprintf(dst, FNFORMAT,
- trimslash(fptr->ar_longname));
- else
- (void) sprintf(dst, FNFORMAT, fptr->ar_name);
- (void) sprintf(dst+16, TLFORMAT, fptr->ar_date,
- (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid,
- (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding,
- ARFMAG);
- arwrite(name, nfd, dst, sizeof (struct ar_hdr));
-
- if (!(fptr->ar_flag & F_MALLOCED) &&
- !(fptr->ar_flag & F_MMAPED) &&
- !(fptr->ar_flag & F_ELFRAW)) {
- f = fopen(fptr->ar_pathname, "r");
- if (stat(fptr->ar_pathname, &stbuf) < 0) {
- (void) fclose(f);
- f = NULL;
- }
- if (f == NULL) {
- error_message(SYS_OPEN_ERROR,
- SYSTEM_ERROR, strerror(errno),
- fptr->ar_longname);
- exit(1);
- } else {
- if ((fptr->ar_contents = (char *)
- malloc(ROUNDUP(stbuf.st_size))) == NULL) {
- error_message(MALLOC_ERROR,
- PLAIN_ERROR, (char *)0);
- exit(1);
- }
- if (fread(fptr->ar_contents,
- sizeof (char),
- stbuf.st_size, f) != stbuf.st_size) {
- error_message(SYS_READ_ERROR,
- SYSTEM_ERROR, strerror(errno),
- fptr->ar_longname);
- exit(1);
- }
- }
- arwrite(name, nfd, fptr->ar_contents, fptr->ar_size);
- (void) fclose(f);
- free(fptr->ar_contents);
- } else {
- arwrite(name, nfd, fptr->ar_contents, fptr->ar_size);
- if (fptr->ar_flag & F_MALLOCED) {
- (void) free(fptr->ar_contents);
- fptr->ar_flag &= ~(F_MALLOCED);
- }
- }
-
- if (fptr->ar_size & 0x1) {
- arwrite(name, nfd, "\n", 1);
- }
-
- if (fptr->ar_padding) {
- int i = fptr->ar_padding;
- while (i) {
- arwrite(name, nfd, "\n", 1);
- --i;
- }
- }
- }
+static const char *
+make_tmpname(const char *filename) {
+ char *slash, *tmpname;
+ size_t prefix_cnt = 0;
/*
- * All preparation for writing is done.
+ * If there is a path prefix in front of the filename, we
+ * want to put the temporary file in the same directory.
+ * Determine the length of the path.
*/
- (void) elf_end(cmd_info->arf);
- (void) close(cmd_info->afd);
-
- if (!new_archive) {
- (void) ar_rename(new_name, name);
+ slash = strrchr(filename, '/');
+ if (slash != NULL)
+ prefix_cnt = slash - filename + 1;
+ tmpname = malloc(prefix_cnt + MSG_STR_MKTEMP_SIZE + 1);
+ if (tmpname == NULL) {
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
+ exit(1);
}
- return (dst);
+ if (prefix_cnt > 0)
+ (void) strncpy(tmpname, filename, prefix_cnt);
+ (void) strcpy(tmpname + prefix_cnt, MSG_ORIG(MSG_STR_MKTEMP));
+ (void) mktemp(tmpname);
+
+ return (tmpname);
}
diff --git a/usr/src/cmd/sgs/ar/common/global.c b/usr/src/cmd/sgs/ar/common/global.c
deleted file mode 100644
index bff4ca37b8..0000000000
--- a/usr/src/cmd/sgs/ar/common/global.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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 (c) 1988 AT&T */
-/* All Rights Reserved */
-
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "inc.h"
-
-ARFILE *listhead, *listend;
-
-int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
diff --git a/usr/src/cmd/sgs/ar/common/inc.h b/usr/src/cmd/sgs/ar/common/inc.h
index e7d14df1cd..9ef5735924 100644
--- a/usr/src/cmd/sgs/ar/common/inc.h
+++ b/usr/src/cmd/sgs/ar/common/inc.h
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -33,219 +33,123 @@
#define _INC_H
#include <stdio.h>
-#include <sys/param.h>
-#include <ar.h>
+#include <stdarg.h>
+#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
-#include "sgs.h"
-#include <stdarg.h>
-#include <sys/mman.h>
-
-#ifndef UID_NOBODY
-#define UID_NOBODY 60001
-#endif
-
-#ifndef GID_NOBODY
-#define GID_NOBODY 60001
-#endif
-
-#include <stdlib.h>
-
-#include "libelf.h"
-
#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
-
+#include <sys/types.h>
+#include <sys/param.h>
#include <time.h>
#include <locale.h>
+#include <ar.h>
+#include <libelf.h>
+#include "sgs.h"
+#include "msg.h"
-#define SUID 04000
-#define SGID 02000
-#define ROWN 0400
-#define WOWN 0200
-#define XOWN 0100
-#define RGRP 040
-#define WGRP 020
-#define XGRP 010
-#define ROTH 04
-#define WOTH 02
-#define XOTH 01
-#define STXT 01000
-
-#define opt_FLAG(_x, ch) ((_x->opt_flgs & ch))
#define CHUNK 500
#define SYMCHUNK 1000
#define SNAME 16
#define ROUNDUP(x) (((x) + 1) & ~1)
-#define LONGDIRNAME "// "
-#define SYMDIRNAME "/ " /* symbol directory filename */
-#define FNFORMAT "%-16s" /* filename format */
-#define TLFORMAT "%-12ld%-6u%-6u%-8o%-10ld%-2s" /* trailer format */
-#define FORMAT FNFORMAT TLFORMAT
#define DATESIZE 60 /* sizeof (struct ar_hdr) */
-#define PLAIN_ERROR 0
-#define LIBELF_ERROR 1
-#define SYSTEM_ERROR 2
-
typedef struct arfile ARFILE;
-typedef ARFILE * ARFILEP;
-
-#define AR_MAX_BYTES_IN_MEM 0x20000000 /* 512 Mb */
+typedef ARFILE *ARFILEP;
-struct arfile
-{
- char ar_name[SNAME]; /* info from archive member header */
- time_t ar_date;
- int ar_uid;
- int ar_gid;
+/*
+ * Per-member state, help on listhead/listend list.
+ */
+struct arfile {
+ char ar_name[SNAME]; /* info from archive member header */
+ time_t ar_date;
+ int ar_uid;
+ int ar_gid;
unsigned long ar_mode;
- long ar_size;
- char *ar_longname;
- char *ar_rawname;
- Elf *ar_elf; /* My elf descriptor */
- char *ar_pathname;
- char *ar_contents;
- long ar_offset; /* The member offset */
- unsigned char ar_flag;
- unsigned char ar_padding; /* padding for CLASS64 */
- ARFILE *ar_next;
+ size_t ar_size;
+ char *ar_longname;
+ char *ar_rawname;
+ Elf *ar_elf; /* My elf descriptor */
+ char *ar_pathname;
+ char *ar_contents;
+ size_t ar_offset; /* The member offset */
+ unsigned char ar_flag;
+ unsigned char ar_padding; /* # padding bytes following data */
+ ARFILE *ar_next; /* Next member in linked list or NULL */
};
+/*
+ * Command function. There is one of these for each operation
+ * ar can perform (r, x, etc).
+ */
+struct cmd_info;
+typedef void Cmd_func(struct cmd_info *);
+
+/* Command information block */
typedef struct cmd_info {
- char *arnam; /* Archive file name */
- int afd; /* fd for the archive file */
- Elf *arf; /* Elf descriptor for the archive */
- char *ponam;
- char **namv;
- int namc;
- int opt_flgs; /* lower case options */
- int OPT_flgs; /* upper case options */
- int (*comfun)();
- int modified;
- unsigned long bytes_in_mem;
+ char *arnam; /* Archive file name */
+ int afd; /* fd for the archive file */
+ Elf *arf; /* Elf descriptor for the archive */
+ char *ponam; /* Position Name (-a, -b/-i) */
+ char **namv; /* Member names from command line */
+ int namc; /* # of member names in namv */
+ int opt_flgs; /* options */
+ Cmd_func *comfun; /* function to carry out command */
+ int modified; /* Set if need to write archive */
} Cmd_info;
/*
- * options
+ * options (Cmd_info opt_flgs)
*/
-#define a_FLAG 0x0001
-#define b_FLAG 0x0002
-#define c_FLAG 0x0004
-#define d_FLAG 0x0008
-#define l_FLAG 0x0020
-#define m_FLAG 0x0040
-#define p_FLAG 0x0080
-#define q_FLAG 0x0100
-#define r_FLAG 0x0200
-#define s_FLAG 0x0400
-#define t_FLAG 0x0800
-#define u_FLAG 0x1000
-#define v_FLAG 0x2000
-#define x_FLAG 0x4000
-#define z_FLAG 0x8000
-
-#define C_FLAG 0x0001
-#define M_FLAG 0x0002
-#define T_FLAG 0x0004
+#define a_FLAG 0x00000001
+#define b_FLAG 0x00000002
+#define c_FLAG 0x00000004
+#define C_FLAG 0x00000008
+#define d_FLAG 0x00000010
+#define m_FLAG 0x00000020
+#define p_FLAG 0x00000040
+#define q_FLAG 0x00000080
+#define r_FLAG 0x00000100
+#define s_FLAG 0x00000200
+#define S_FLAG 0x00000400
+#define t_FLAG 0x00000800
+#define T_FLAG 0x00001000
+#define u_FLAG 0x00002000
+#define v_FLAG 0x00004000
+#define x_FLAG 0x00008000
+#define z_FLAG 0x00010000
/*
- * Where is the file contents from ?
+ * Member flags (ARFILE ar_flag)
*/
-#define F_ELFRAW 0x01 /* Mmaped via elf_raw() */
-#define F_MMAPED 0x02 /* Mmaped file contents */
-#define F_MALLOCED 0x04 /* Malloced file contents */
-#define F_CLASS32 0x08 /* This is ELFCLASS32 */
-#define F_CLASS64 0x10 /* This is ELFCLASS64 */
+#define F_ELFRAW 0x01 /* ar_contents data via elf_rawfile */
+#define F_CLASS32 0x02 /* ELFCLASS32 */
+#define F_CLASS64 0x04 /* ELFCLASS64 */
/*
* Function prototypes
*/
-int qcmd(Cmd_info *);
-int rcmd(Cmd_info *);
-int dcmd(Cmd_info *);
-int xcmd(Cmd_info *);
-int pcmd(Cmd_info *);
-int mcmd(Cmd_info *);
-int tcmd(Cmd_info *);
-
-int getaf(Cmd_info *);
-char *writefile(Cmd_info *cmd_info);
-void error_message(int, ...);
-
-ARFILE *getfile(Cmd_info *);
-ARFILE *newfile();
+Cmd_func qcmd;
+Cmd_func rcmd;
+Cmd_func dcmd;
+Cmd_func xcmd;
+Cmd_func pcmd;
+Cmd_func mcmd;
+Cmd_func tcmd;
+
+extern ARFILE *listhead, *listend;
+
+extern void establish_sighandler(void (*)());
+extern int getaf(Cmd_info *);
+extern ARFILE *getfile(Cmd_info *);
+extern ARFILE *newfile(void);
+extern char *trim(char *);
+extern void writefile(Cmd_info *cmd_info);
-char *trim(char *);
-
-/*
- * Error definitions
- */
-#define MALLOC_ERROR 0
-#define USAGE_01_ERROR 1
-#define NOT_FOUND_01_ERROR 2
-#define USAGE_02_ERROR 3
-#define USAGE_03_ERROR 4
-#define USAGE_04_ERROR 5
-#define SYS_OPEN_ERROR 6
-#define SYS_READ_ERROR 7
-#define NOT_FOUND_02_ERROR 8
-#define PATHCONF_ERROR 9
-#define SYS_WRITE_ERROR 10
-#define LOCALTIME_ERROR 11
-#define USAGE_05_ERROR 12
-#define ELF_VERSION_ERROR 13
-#define NOT_ARCHIVE_ERROR 14
-#define USAGE_06_ERROR 15
-#define ELF_MALARCHIVE_ERROR 16
-#define SYS_LSEEK_ERROR 17
-#define NOT_FOUND_03_ERROR 18
-#define SYS_LSEEK_02_ERROR 19
-#define SYS_LSEEK_03_ERROR 20
-#define SYS_LSEEK_04_ERROR 21
-#define DEBUG_INFO_01_ERROR 22
-#define DEBUG_INFO_02_ERROR 23
-#define ELF_INTERNAL_RAND_ERROR 24
-#define ELF_BEGIN_01_ERROR 25
-#define DEBUG_INFO_03_ERROR 26
-#define ELF_BEGIN_02_ERROR 27
-#define ELF_BEGIN_03_ERROR 28
-#define ARCHIVE_IN_ARCHIVE_ERROR 29
-#define ARCHIVE_USAGE_ERROR 30
-#define INTERNAL_01_ERROR 31
-#define ELF_GETSCN_01_ERROR 32
-#define ELF_GETSCN_02_ERROR 33
-#define ELF_GETDATA_01_ERROR 34
-#define ELF_GETDATA_02_ERROR 35
-#define W_ELF_NO_DATA_01_ERROR 36
-#define W_ELF_NO_DATA_02_ERROR 37
-#define INTERNAL_02_ERROR 38
-#define DIAG_01_ERROR 39
-#define BER_MES_CREATE_ERROR 40
-#define SYS_CREATE_01_ERROR 41
-#define SYS_WRITE_02_ERROR 42
-#define BER_MES_WRITE_ERROR 43
-#define SYS_WRITE_03_ERROR 44
-#define SBROW_01_ERROR 45
-#define SBROW_02_ERROR 46
-#define SBROW_03_ERROR 47
-#define SYMTAB_01_ERROR 48
-#define SYMTAB_02_ERROR 49
-#define SYMTAB_03_ERROR 50
-#define SYMTAB_04_ERROR 51
-#define SYMTAB_05_ERROR 52
-#define SYMTAB_06_ERROR 53
-#define SYMTAB_07_ERROR 54
-#define ELF_01_ERROR 55
-#define ELF_02_ERROR 56
-#define OVERRIDE_WARN_ERROR 57
-#define SYS_WRITE_04_ERROR 58
-#define WARN_USER_ERROR 59
-#define ELF_RAWFILE_ERROR 60
#endif /* _INC_H */
diff --git a/usr/src/cmd/sgs/ar/common/extern.h b/usr/src/cmd/sgs/ar/common/lintsup.c
index 4b1de6efd3..e456077e2e 100644
--- a/usr/src/cmd/sgs/ar/common/extern.h
+++ b/usr/src/cmd/sgs/ar/common/lintsup.c
@@ -2,9 +2,8 @@
* 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.
+ * Common Development and Distribution License (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
* or http://www.opensolaris.org/os/licensing.
@@ -19,11 +18,20 @@
*
* CDDL HEADER END
*/
-/* Copyright (c) 1988 AT&T */
-/* All Rights Reserved */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * Supplemental Pseudo-code to get lint to consider these symbols used.
+ */
+#include <msg.h>
-#pragma ident "%Z%%M% %I% %E% SMI"
+#pragma error_messages(off, E_STATIC_UNUSED)
-extern ARFILE *listhead, *listend;
-extern int signum[];
+static void
+foo(void)
+{
+ (void) _ar_msg((Msg)&__ar_msg[0]);
+}
diff --git a/usr/src/cmd/sgs/ar/common/main.c b/usr/src/cmd/sgs/ar/common/main.c
index c5c94d062c..a452d403ff 100644
--- a/usr/src/cmd/sgs/ar/common/main.c
+++ b/usr/src/cmd/sgs/ar/common/main.c
@@ -22,52 +22,82 @@
/* All Rights Reserved */
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include "inc.h"
-#include "extern.h"
-
-static char *arnam;
+#include "conv.h"
/*
- * Function prototypes
+ * Forward declarations
*/
static void setup(int, char **, Cmd_info *);
-static void setcom(Cmd_info *, int (*)());
+static void setcom(Cmd_info *, Cmd_func);
static void usage(void);
static void sigexit(int sig);
static int notfound(Cmd_info *);
static void check_swap();
-#define OPTSTR ":a:b:i:vucsrdxtplmqVCTzM"
+const char *
+_ar_msg(Msg mid)
+{
+ return (gettext(MSG_ORIG(mid)));
+}
+
-int
-main(int argc, char **argv)
+void
+establish_sighandler(void (*handler)())
{
+ static const int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
int i;
+
+ if (handler == SIG_IGN) {
+ /* Ignore all the specified signals */
+ for (i = 0; signum[i]; i++)
+ (void) signal(signum[i], SIG_IGN);
+
+ } else {
+ /*
+ * Set any signal that doesn't default to being ignored
+ * to our signal handler.
+ */
+ for (i = 0; signum[i]; i++)
+ if (signal(signum[i], SIG_IGN) != SIG_IGN)
+ (void) signal(signum[i], handler);
+ }
+}
+
+int
+main(int argc, char **argv, char *envp[])
+{
int fd;
Cmd_info *cmd_info;
int ret;
char *new = NULL;
- char *data = NULL;
- (void) setlocale(LC_ALL, "");
-#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
-#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
+#ifndef XPG4
+ /*
+ * Check for a binary that better fits this architecture.
+ */
+ (void) conv_check_native(argv, envp);
#endif
- (void) textdomain(TEXT_DOMAIN);
- for (i = 0; signum[i]; i++)
- if (signal(signum[i], SIG_IGN) != SIG_IGN)
- (void) signal(signum[i], sigexit);
+ /*
+ * Establish locale.
+ */
+ (void) setlocale(LC_ALL, MSG_ORIG(MSG_STR_EMPTY));
+ (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
+
+ /* Allow a graceful exit up until we start to write an archive */
+ establish_sighandler(sigexit);
+
/*
* Initialize cmd_info
*/
cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info));
if (cmd_info == NULL) {
- error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
exit(1);
}
@@ -80,10 +110,12 @@ main(int argc, char **argv)
if (argv[1][0] != '-') {
new = (char *)malloc(strlen(argv[1]) + 2);
if (new == NULL) {
- error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0);
+ int err = errno;
+ (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
+ strerror(err));
exit(1);
}
- (void) strcpy(new, "-");
+ (void) strcpy(new, MSG_ORIG(MSG_STR_HYPHEN));
(void) strcat(new, argv[1]);
argv[1] = new;
}
@@ -92,37 +124,33 @@ main(int argc, char **argv)
/*
* Check SWAP
*/
- if (opt_FLAG((cmd_info), z_FLAG))
+ if (cmd_info->opt_flgs & z_FLAG)
check_swap();
- if (cmd_info->comfun == 0) {
- if (!(opt_FLAG((cmd_info), d_FLAG) ||
- opt_FLAG(cmd_info, r_FLAG) ||
- opt_FLAG(cmd_info, q_FLAG) || opt_FLAG(cmd_info, t_FLAG) ||
- opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) ||
- opt_FLAG(cmd_info, x_FLAG))) {
- error_message(USAGE_01_ERROR, PLAIN_ERROR, (char *)0);
+ if (cmd_info->comfun == NULL) {
+ if ((cmd_info->opt_flgs & (d_FLAG | r_FLAG | q_FLAG |
+ t_FLAG | p_FLAG | m_FLAG | x_FLAG)) == 0) {
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_01));
exit(1);
}
}
- cmd_info->modified = opt_FLAG(cmd_info, s_FLAG);
+ cmd_info->modified = (cmd_info->opt_flgs & s_FLAG);
fd = getaf(cmd_info);
if ((fd == -1) &&
- (opt_FLAG(cmd_info, d_FLAG) || opt_FLAG(cmd_info, t_FLAG) ||
- opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) ||
- opt_FLAG(cmd_info, x_FLAG) ||
- (opt_FLAG(cmd_info, r_FLAG) && (opt_FLAG(cmd_info, a_FLAG) ||
- opt_FLAG(cmd_info, b_FLAG))))) {
- error_message(NOT_FOUND_01_ERROR,
- PLAIN_ERROR, (char *)0, arnam);
+ (cmd_info->opt_flgs &
+ (d_FLAG | m_FLAG | p_FLAG | t_FLAG | x_FLAG)) ||
+ ((cmd_info->opt_flgs & r_FLAG) &&
+ (cmd_info->opt_flgs & (a_FLAG | b_FLAG)))) {
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_AR),
+ cmd_info->arnam);
exit(1);
}
(*cmd_info->comfun)(cmd_info);
if (cmd_info->modified) {
- data = writefile(cmd_info);
+ writefile(cmd_info);
} else
(void) close(fd);
@@ -131,10 +159,9 @@ main(int argc, char **argv)
/*
* Check SWAP
*/
- if (opt_FLAG((cmd_info), z_FLAG))
+ if (cmd_info->opt_flgs & z_FLAG)
check_swap();
- free(data);
free(new);
free(cmd_info);
return (ret);
@@ -142,7 +169,7 @@ main(int argc, char **argv)
}
/*
- * Option hadning function.
+ * Option handing function.
* Using getopt(), following xcu4 convention.
*/
static void
@@ -152,7 +179,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
int c;
int usage_err = 0;
- while ((c = getopt(argc, argv, OPTSTR)) != -1) {
+ while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
switch (c) {
case 'a': /* position after named archive member file */
cmd_info->opt_flgs |= a_FLAG;
@@ -174,8 +201,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
setcom(cmd_info, dcmd);
cmd_info->opt_flgs |= d_FLAG;
break;
- case 'l': /* temporary directory */
- cmd_info->opt_flgs |= l_FLAG;
+ case 'l': /* ignored */
break;
case 'm':
/*
@@ -213,6 +239,9 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
case 's': /* force symbol table regeneration */
cmd_info->opt_flgs |= s_FLAG;
break;
+ case 'S': /* Build SYM64 symbol table */
+ cmd_info->opt_flgs |= S_FLAG;
+ break;
case 't':
/*
* key operation:
@@ -244,29 +273,33 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
* adjust command line access accounting
*/
if (Vflag == 0) {
- (void) fprintf(stderr, "ar: %s %s\n",
+ (void) fprintf(stderr,
+ MSG_ORIG(MSG_FMT_VERSION),
(const char *)SGU_PKG,
(const char *)SGU_REL);
Vflag++;
}
break;
case 'C':
- cmd_info->OPT_flgs |= C_FLAG;
+ cmd_info->opt_flgs |= C_FLAG;
break;
case 'M':
- cmd_info->OPT_flgs |= M_FLAG;
+ /*
+ * -M was an original undocumented AT&T feature that
+ * would force the use of mmap() instead of read()
+ * for pulling file data into the process before
+ * writing it to the archive. Ignored.
+ */
break;
case 'T':
- cmd_info->OPT_flgs |= T_FLAG;
+ cmd_info->opt_flgs |= T_FLAG;
break;
case ':':
- error_message(USAGE_02_ERROR,
- PLAIN_ERROR, (char *)0, optopt);
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_02), optopt);
usage_err++;
break;
case '?':
- error_message(USAGE_03_ERROR,
- PLAIN_ERROR, (char *)0, optopt);
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_03), optopt);
usage_err++;
break;
}
@@ -275,7 +308,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
if (usage_err || argc - optind < 1)
usage();
- cmd_info->arnam = arnam = argv[optind];
+ cmd_info->arnam = argv[optind];
cmd_info->namv = &argv[optind+1];
cmd_info->namc = argc - optind - 1;
}
@@ -286,10 +319,10 @@ setup(int argc, char *argv[], Cmd_info *cmd_info)
* Check that only one key is indicated.
*/
static void
-setcom(Cmd_info *cmd_info, int (*fun)())
+setcom(Cmd_info *cmd_info, Cmd_func *fun)
{
if (cmd_info->comfun != 0) {
- error_message(USAGE_04_ERROR, PLAIN_ERROR, (char *)0);
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE_04));
exit(1);
}
cmd_info->comfun = fun;
@@ -298,14 +331,7 @@ setcom(Cmd_info *cmd_info, int (*fun)())
static void
usage(void)
{
- (void) fprintf(stderr, gettext(
-"usage: ar -d[-vV] archive file ...\n"
-" ar -m[-abivV] [posname] archive file ...\n"
-" ar -p[-vV][-s] archive [file ...]\n"
-" ar -q[-cuvV] [-abi] [posname] [file ...]\n"
-" ar -r[-cuvV] [-abi] [posname] [file ...]\n"
-" ar -t[-vV][-s] archive [file ...]\n"
-" ar -x[-vV][-sCT] archive [file ...]\n"));
+ (void) fprintf(stderr, MSG_INTL(MSG_USAGE));
exit(1);
}
@@ -326,8 +352,8 @@ notfound(Cmd_info *cmd_info)
n = 0;
for (i = 0; i < cmd_info->namc; i++)
if (cmd_info->namv[i]) {
- error_message(NOT_FOUND_03_ERROR,
- PLAIN_ERROR, (char *)0, cmd_info->namv[i]);
+ (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_FILE),
+ cmd_info->namv[i]);
n++;
}
return (n);
@@ -339,5 +365,5 @@ notfound(Cmd_info *cmd_info)
static void
check_swap(void)
{
- (void) system("/usr/sbin/swap -s");
+ (void) system(MSG_ORIG(MSG_CMD_SWAP));
}
diff --git a/usr/src/cmd/sgs/ar/common/message.c b/usr/src/cmd/sgs/ar/common/message.c
deleted file mode 100644
index 38232e45f9..0000000000
--- a/usr/src/cmd/sgs/ar/common/message.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "inc.h"
-
-static const char *msg[] = {
-/* MALLOC_ERROR */
-"ar: could not allocate memory.\n",
-/* USAGE_01_ERROR */
-"ar: one of [drqtpmx] must be specified\n",
-/* NOT_FOUND_01_ERROR */
-"ar: archive, %s, not found\n",
-/* USAGE_02_ERROR */
-"ar: -%c requires an operand\n",
-/* USAGE_03_ERROR */
-"ar: bad option `%c'\n",
-/* USAGE_04_ERROR */
-"ar: only one of [drqtpmx] allowed\n",
-/* SYS_OPEN_ERROR */
-"ar: cannot open %s\n",
-/* SYS_READ_ERROR */
-"ar: cannot read %s\n",
-/* NOT_FOUND_02_ERROR */
-"ar: posname, %s, not found\n",
-/* PATHCONF_ERROR */
-"ar: -T failed to calculate file name length.\n",
-/* SYS_WRITE_ERROR */
-"ar: %s: cannot write\n",
-/* LOCALTIME_ERROR */
-"ar: don't have enough space to store the date\n",
-/* USAGE_05_ERROR */
-"ar: abi not allowed with q\n",
-/* ELF_VERSION_ERROR */
-"ar: libelf.a out of date\n",
-/* NOT_ARCHIVE_ERROR */
-"ar: %s not in archive format\n",
-/* USAGE_06_ERROR */
-"ar: %s taken as mandatory 'posname' with keys 'abi'\n",
-/* ELF_MALARCHIVE_ERROR */
-"ar: %s: malformed archive (at %ld)\n",
-/* SYS_LSEEK_ERROR */
-"ar: cannot lseek\n",
-/* NOT_FOUND_03_ERROR */
-"ar: %s not found\n",
-/* SYS_LSEEK_02_ERROR */
-"ar: lseek(current) errno=%d\n",
-/* SYS_LSEEK_03_ERROR */
-"ar: lseek(f->offset) errno=%d\n",
-/* SYS_LSEEK_04_ERROR */
-"ar: Problem seeking\n",
-/* DEBUG_INFO_01_ERROR */
-"ar: currentloc %d intendedloc %d resultingloc %d\n",
-/* DEBUG_INFO_02_ERROR */
-"ar: ar_name '%s' longname '%s'\n",
-/* ELF_INTERNAL_RAND_ERROR */
-"ar: internal or system error; archive file has been scribbled\n",
-/* ELF_BEGIN_01_ERROR */
-"ar: archive is corrupted/possible end-of-archive\n",
-/* DEBUG_INFO_03_ERROR */
-"ar: can not find member'%s' at offset 0x%x\n",
-/* ELF_BEGIN_02_ERROR */
-"ar: cannot elf_begin() %s.\n",
-/* ELF_BEGIN_03_ERROR */
-"ar: cannot elf_begin().\n",
-/* ARCHIVE_IN_ARCHIVE_ERROR */
-"ar: %s is in archive format - embedded archives are not allowed\n",
-/* ARCHIVE_USAGE_ERROR */
-"ar: embedded archives are not allowed.\n",
-/* INTERNAL_01_ERROR */
-"ar: internal error - cannot tell whether file is included in archive or not\n",
-/* ELF_GETSCN_01_ERROR */
-"ar: %s has no section header or bad elf format.\n",
-/* ELF_GETSCN_02_ERROR */
-"ar: no section header or bad elf format.\n",
-/* ELF_GETDATA_01_ERROR */
-"ar: %s has bad elf format.\n",
-/* ELF_GETDATA_02_ERROR */
-"ar: bad elf format.\n",
-/* W_ELF_NO_DATA_01_ERROR */
-"ar: %s has no data in section header table.\n",
-/* W_ELF_NO_DATA_02_ERROR */
-"ar: No data in section header table.\n",
-/* INTERNAL_02_ERROR */
-"ar: internal header generation error\n",
-/* DIAG_01_ERROR */
-"ar: diagnosis: ERRNO=%d\n",
-/* BER_MES_CREATE_ERROR */
-"ar: creating %s\n",
-/* SYS_CREATE_01_ERROR */
-"ar: cannot create %s\n",
-/* SYS_WRITE_02_ERROR */
-"ar: cannot write %s\n",
-/* BER_MES_WRITE_ERROR */
-"ar: writing %s\n",
-/* SYS_WRITE_03_ERROR */
-"ar: cannot write archive\n",
-/* SBROW_01_ERROR */
-"ar: No data in stab table.\n",
-/* SBROW_02_ERROR */
-"ar: No data in stab string table.\n",
-/* SBROW_03_ERROR */
-"ar: No data in stab table - size is 0\n",
-/* SYMTAB_01_ERROR */
-"ar: Symbol table entry size is 0!\n",
-/* SYMTAB_02_ERROR */
-"ar: %s has no string table for symbol names\n",
-/* SYMTAB_03_ERROR */
-"ar: No string table for symbol names\n",
-/* SYMTAB_04_ERROR */
-"ar: %s has no data in string table\n",
-/* SYMTAB_05_ERROR */
-"ar: No data in string table\n",
-/* SYMTAB_06_ERROR */
-"ar: %s has no data in string table - size is 0\n",
-/* SYMTAB_07_ERROR */
-"ar: No data in string table - size is 0\n",
-/* ELF_01_ERROR */
-"ar: %s caused libelf error: %s\n",
-/* ELF_02_ERROR */
-"ar: libelf error: %s\n",
-/* OVERRIDE_WARN_ERROR */
-"ar: %s already exists. Will not be extracted\n",
-/* SYS_WRITE_04_ERROR */
-"ar: writing to %s failed.\n",
-/* WARN_USER_ERROR */
-"\tThe original archive is destroyed.\n",
-/* ELF_RAWFILE_ERROR */
-"ar: elf_rawfile() failed.\n",
-};
-
-void
-error_message(int args, ...)
-{
- int mes = args;
- char *message = gettext((char *)msg[mes]);
- int flag;
- char *sys_mes;
- va_list ap;
- va_start(ap, args);
-
- flag = va_arg(ap, int);
- sys_mes = va_arg(ap, char *);
-
- switch (mes) {
- case MALLOC_ERROR:
- case USAGE_01_ERROR:
- case USAGE_04_ERROR:
- case PATHCONF_ERROR:
- case LOCALTIME_ERROR:
- case USAGE_05_ERROR:
- case ARCHIVE_USAGE_ERROR:
- case INTERNAL_01_ERROR:
- case INTERNAL_02_ERROR:
- case SBROW_01_ERROR:
- case SBROW_02_ERROR:
- case SBROW_03_ERROR:
- case SYMTAB_01_ERROR:
- case SYMTAB_03_ERROR:
- case SYMTAB_05_ERROR:
- case SYMTAB_07_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message);
- break;
- case ARCHIVE_IN_ARCHIVE_ERROR:
- case NOT_FOUND_01_ERROR:
- case NOT_FOUND_02_ERROR:
- case NOT_FOUND_03_ERROR:
- case NOT_ARCHIVE_ERROR:
- case USAGE_06_ERROR:
- case BER_MES_CREATE_ERROR:
- case BER_MES_WRITE_ERROR:
- case SYMTAB_02_ERROR:
- case SYMTAB_04_ERROR:
- case SYMTAB_06_ERROR:
- case OVERRIDE_WARN_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, char *));
- break;
- case USAGE_02_ERROR:
- case USAGE_03_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, int));
- break;
- case DIAG_01_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, int));
- break;
- case DEBUG_INFO_01_ERROR: {
- int a1, a2, a3;
-
- a1 = va_arg(ap, int);
- a2 = va_arg(ap, int);
- a3 = va_arg(ap, int);
- /* LINTED: variable format */
- (void) fprintf(stderr, message, a1, a2, a3);
- break;
- }
- case DEBUG_INFO_02_ERROR: {
- char *a1, *a2;
-
- a1 = va_arg(ap, char *);
- a2 = va_arg(ap, char *);
- /* LINTED: variable format */
- (void) fprintf(stderr, message, a1, a2);
- break;
- }
- case DEBUG_INFO_03_ERROR: {
- char *a1;
- int a2;
-
- a1 = va_arg(ap, char *);
- a2 = va_arg(ap, int);
- /* LINTED: variable format */
- (void) fprintf(stderr, message, a1, a2);
- break;
- }
- /*
- * system call failure
- */
- case SYS_LSEEK_ERROR:
- case SYS_LSEEK_04_ERROR:
- case SYS_WRITE_03_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message);
- break;
- case SYS_OPEN_ERROR:
- case SYS_READ_ERROR:
- case SYS_WRITE_ERROR:
- case SYS_WRITE_02_ERROR:
- case SYS_CREATE_01_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, char *));
- break;
- case SYS_LSEEK_02_ERROR:
- case SYS_LSEEK_03_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, int));
- break;
- /*
- * Elf related errors
- */
- case ELF_VERSION_ERROR:
- case ELF_INTERNAL_RAND_ERROR:
- case ELF_BEGIN_02_ERROR:
- case ELF_GETSCN_02_ERROR:
- case ELF_GETDATA_02_ERROR:
- case W_ELF_NO_DATA_02_ERROR:
- case ELF_RAWFILE_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message);
- break;
- case ELF_BEGIN_01_ERROR:
- case ELF_GETSCN_01_ERROR:
- case ELF_GETDATA_01_ERROR:
- case W_ELF_NO_DATA_01_ERROR:
- case ELF_02_ERROR:
- /* LINTED: variable format */
- (void) fprintf(stderr, message, va_arg(ap, char *));
- break;
- case ELF_01_ERROR: {
- char *a1, *a2;
-
- a1 = va_arg(ap, char *);
- a2 = va_arg(ap, char *);
- /* LINTED: variable format */
- (void) fprintf(stderr, message, a1, a2);
- break;
- }
- case ELF_MALARCHIVE_ERROR: {
- char *a1;
- long a2;
-
- a1 = va_arg(ap, char *);
- a2 = va_arg(ap, long);
- /* LINTED: variable format */
- (void) fprintf(stderr, message, a1, a2);
- break;
- }
- default:
- (void) fprintf(stderr, "internal error: error_message(%d)\n",
- mes);
- exit(100);
- }
-
- if (flag != PLAIN_ERROR)
- (void) fprintf(stderr, "\t%s\n", sys_mes);
- va_end(ap);
-}
diff --git a/usr/src/cmd/sgs/ar/i386/Makefile b/usr/src/cmd/sgs/ar/i386/Makefile
index 0955bc546b..65c061d3b8 100644
--- a/usr/src/cmd/sgs/ar/i386/Makefile
+++ b/usr/src/cmd/sgs/ar/i386/Makefile
@@ -2,9 +2,8 @@
# 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.
+# Common Development and Distribution License (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
# or http://www.opensolaris.org/os/licensing.
@@ -20,13 +19,17 @@
# CDDL HEADER END
#
#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# Copyright (c) 1996 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
include ../Makefile.com
.KEEP_STATE:
+all: $(PROG) $(XPG4)
+
+install \
+package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK)
+
+
+
include ../Makefile.targ
diff --git a/usr/src/cmd/sgs/ar/sparc/Makefile b/usr/src/cmd/sgs/ar/sparc/Makefile
index 0955bc546b..eed82bcded 100644
--- a/usr/src/cmd/sgs/ar/sparc/Makefile
+++ b/usr/src/cmd/sgs/ar/sparc/Makefile
@@ -2,9 +2,8 @@
# 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.
+# Common Development and Distribution License (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
# or http://www.opensolaris.org/os/licensing.
@@ -20,13 +19,15 @@
# CDDL HEADER END
#
#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# Copyright (c) 1996 by Sun Microsystems, Inc.
-# All rights reserved.
+# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
include ../Makefile.com
.KEEP_STATE:
+all: $(PROG) $(XPG4)
+
+install \
+package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK)
+
include ../Makefile.targ
diff --git a/usr/src/cmd/sgs/ar/sparcv9/Makefile b/usr/src/cmd/sgs/ar/sparcv9/Makefile
new file mode 100644
index 0000000000..dc3747cacb
--- /dev/null
+++ b/usr/src/cmd/sgs/ar/sparcv9/Makefile
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (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
+# or http://www.opensolaris.org/os/licensing.
+# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../Makefile.com
+
+.KEEP_STATE:
+
+LLDFLAGS = $(LLDFLAGS64)
+CONVLIBDIR = $(CONVLIBDIR64)
+ELFLIBDIR = $(ELFLIBDIR64)
+LDDBGLIBDIR = $(LDDBGLIBDIR64)
+LINTFLAGS64 += $(VAR_LINTFLAGS64)
+
+ROOTPROG = $(ROOTPROG64)
+
+all: $(PROG)
+
+package \
+install: all $(ROOTPROG64) $(ROOTCCSBINLINK64)
+
+include ../Makefile.targ
+include ../../Makefile.sub.64
diff --git a/usr/src/cmd/sgs/dump/common/dump.c b/usr/src/cmd/sgs/dump/common/dump.c
index c542ed8171..665ee85e49 100644
--- a/usr/src/cmd/sgs/dump/common/dump.c
+++ b/usr/src/cmd/sgs/dump/common/dump.c
@@ -23,8 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Get definitions for the relocation types supported. */
@@ -1808,7 +1807,8 @@ dump_ar_hdr(int fd, Elf *elf_file, char *filename)
elf_errmsg(-1));
continue;
}
- if (strcmp(p_ar->ar_name, "/") == 0) {
+ if ((strcmp(p_ar->ar_name, "/") == 0) ||
+ (strcmp(p_ar->ar_name, "/SYM64/") == 0)) {
if (g_flag)
ar_sym_read(elf_file, filename);
} else if (strcmp(p_ar->ar_name, "//") == 0) {
@@ -1893,8 +1893,7 @@ dump_ar_files(int fd, Elf *elf_file, char *filename)
prog_name, filename, elf_errmsg(-1));
return;
}
- if ((strcmp(p_ar->ar_name, "/") == 0) ||
- (strcmp(p_ar->ar_name, "//") == 0)) {
+ if (p_ar->ar_name[0] == '/') {
cmd = elf_next(arf);
(void) elf_end(arf);
continue;
diff --git a/usr/src/cmd/sgs/dump/common/fcns.c b/usr/src/cmd/sgs/dump/common/fcns.c
index 6d3a933991..2ce89728e3 100644
--- a/usr/src/cmd/sgs/dump/common/fcns.c
+++ b/usr/src/cmd/sgs/dump/common/fcns.c
@@ -23,15 +23,14 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
-#include <libelf.h>
+#include <_libelf.h>
#include <limits.h>
#include "conv.h"
#include "dump.h"
@@ -47,7 +46,8 @@ void
ar_sym_read(Elf *elf, char *filename)
{
Elf_Arsym * arsym;
- size_t cnt, ptr;
+ size_t cnt, ptr, is64;
+ const char *fmt;
if ((arsym = elf_getarsym(elf, &ptr)) == NULL) {
(void) fprintf(stderr, "%s: %s: no archive symbol table\n",
@@ -55,18 +55,23 @@ ar_sym_read(Elf *elf, char *filename)
return;
}
+ is64 = (_elf_getarsymwordsize(elf) == 8);
(void) printf("%s:\n", filename);
if (!p_flag) {
(void) printf(" **** ARCHIVE SYMBOL TABLE ****\n");
- (void) printf("%-8s %s\n\n", "Offset", "Name");
+ if (is64) {
+ (void) printf("%-8s %s\n\n", "Offset", "Name");
+ fmt = "%-16.16llx %s\n";
+ } else {
+ (void) printf("%-8s %s\n\n", "Offset", "Name");
+ fmt = "%-8.8llx %s\n";
+ }
}
for (cnt = 0; cnt < ptr; cnt++, arsym++) {
- if (arsym->as_off) {
- /* LINTED */
- (void) printf("%-8.8x %s\n", (int)arsym->as_off,
+ if (arsym->as_off)
+ (void) printf(fmt, EC_XWORD(arsym->as_off),
(arsym->as_name ? arsym->as_name : ""));
- }
}
}
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index 5735d19b53..aada7e8e9f 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -243,8 +243,10 @@
@ MSG_ELF_ERR_DATA "\tunable to obtain section data: shstrtab[%lld]\n"
@ MSG_ELF_ERR_SCN "\tunable to obtain section header: section[%d]\n"
@ MSG_ELF_ERR_SCNDATA "\tunable to obtain section data: section[%d]\n"
-@ MSG_ARCHIVE_SYMTAB "\nSymbol Table: (archive)"
-@ MSG_ARCHIVE_FIELDS " index offset member name and symbol"
+@ MSG_ARCHIVE_SYMTAB_32 "\nSymbol Table: (archive, 32-bit offsets)"
+@ MSG_ARCHIVE_SYMTAB_64 "\nSymbol Table: (archive, 64-bit offsets)"
+@ MSG_ARCHIVE_FIELDS_32 " index offset member name and symbol"
+@ MSG_ARCHIVE_FIELDS_64 " index offset member name and symbol"
@ MSG_GOT_MULTIPLE "%s: multiple relocations against \
the same GOT entry ndx: %d addr: 0x%llx\n"
@@ -356,8 +358,10 @@
@ MSG_FMT_INTEGER " %d"
@ MSG_FMT_HASH_INFO "%10.10s %-10s %s"
@ MSG_FMT_CHAIN_INFO "%10.10s %-10s %s"
-@ MSG_FMT_ARSYM1 "%10.10s 0x%8.8x (%s):%s"
-@ MSG_FMT_ARSYM2 "%10.10s 0x%8.8x"
+@ MSG_FMT_ARSYM1_32 "%10.10s 0x%8.8llx (%s):%s"
+@ MSG_FMT_ARSYM2_32 "%10.10s 0x%8.8llx"
+@ MSG_FMT_ARSYM1_64 "%10.10s 0x%16.16llx (%s):%s"
+@ MSG_FMT_ARSYM2_64 "%10.10s 0x%16.16llx"
@ MSG_FMT_ARNAME "%s(%s)"
@ MSG_FMT_NLSTR "\n%s:"
@ MSG_FMT_NLSTRNL "\n%s:\n"
diff --git a/usr/src/cmd/sgs/elfdump/common/main.c b/usr/src/cmd/sgs/elfdump/common/main.c
index 76b6b02d5f..b35da26ecc 100644
--- a/usr/src/cmd/sgs/elfdump/common/main.c
+++ b/usr/src/cmd/sgs/elfdump/common/main.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -32,7 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
-#include <libelf.h>
+#include <_libelf.h>
#include <link.h>
#include <stdarg.h>
#include <unistd.h>
@@ -595,12 +594,29 @@ archive(const char *file, int fd, Elf *elf, uint_t flags,
size_t cnt;
char index[MAXNDXSIZE];
size_t offset = 0, _offset = 0;
+ const char *fmt_arsym1, *fmt_arsym2;
/*
- * Print out all the symbol entries.
+ * Print out all the symbol entries. The format width used
+ * corresponds to whether the archive symbol table is 32
+ * or 64-bit. We see them via Elf_Arhdr as size_t values
+ * in either case with no information loss (see the comments
+ * in libelf/getarsym.c) so this is done simply to improve
+ * the user presentation.
*/
- dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB));
- dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS));
+ if (_elf_getarsymwordsize(elf) == 8) {
+ dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
+ dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));
+
+ fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
+ fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
+ } else {
+ dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
+ dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));
+
+ fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
+ fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
+ }
for (cnt = 0; cnt < ptr; cnt++, arsym++) {
/*
@@ -637,16 +653,15 @@ archive(const char *file, int fd, Elf *elf, uint_t flags,
(void) snprintf(index, MAXNDXSIZE,
MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
if (arsym->as_off)
- dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index,
- /* LINTED */
- (int)arsym->as_off, arhdr ? arhdr->ar_name :
+ dbg_print(0, fmt_arsym1, index,
+ EC_XWORD(arsym->as_off),
+ arhdr ? arhdr->ar_name :
MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
demangle(arsym->as_name, flags) :
MSG_INTL(MSG_STR_NULL)));
else
- dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index,
- /* LINTED */
- (int)arsym->as_off);
+ dbg_print(0, fmt_arsym2, index,
+ EC_XWORD(arsym->as_off));
}
if (_elf)
diff --git a/usr/src/cmd/sgs/include/_libelf.h b/usr/src/cmd/sgs/include/_libelf.h
index d7e8446721..790cc03627 100644
--- a/usr/src/cmd/sgs/include/_libelf.h
+++ b/usr/src/cmd/sgs/include/_libelf.h
@@ -44,6 +44,7 @@ typedef void _elf_execfill_func_t(void *, off_t, size_t);
extern void _elf_execfill(_elf_execfill_func_t *);
extern size_t _elf_getnextoff(Elf *);
extern off_t _elf_getarhdrbase(Elf *);
+extern size_t _elf_getarsymwordsize(Elf *);
extern Elf64_Off _elf_getxoff(Elf_Data *);
extern GElf_Xword _gelf_getdyndtflags_1(Elf *);
extern int _elf_swap_wrimage(Elf *);
diff --git a/usr/src/cmd/sgs/libelf/common/ar.c b/usr/src/cmd/sgs/libelf/common/ar.c
index 9cfa68ad4f..38836fd1c7 100644
--- a/usr/src/cmd/sgs/libelf/common/ar.c
+++ b/usr/src/cmd/sgs/libelf/common/ar.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -29,8 +28,6 @@
* All Rights Reserved
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ar.h>
#include <stdlib.h>
#include <memory.h>
@@ -214,6 +211,11 @@ _elf_armem(Elf *elf, char *file, size_t fsz)
m->m_name[1] = '\0';
else if (f->ar_name[1] == '/' && f->ar_name[2] == ' ') /* "//" */
m->m_name[2] = '\0';
+ else if (f->ar_name[1] == 'S' && f->ar_name[2] == 'Y' &&
+ f->ar_name[3] == 'M' && f->ar_name[4] == '6' &&
+ f->ar_name[5] == '4' && f->ar_name[6] == '/' &&
+ f->ar_name[7] == ' ') /* "/SYM64/" */
+ m->m_name[7] = '\0';
else { /* "/?" */
m->m_hdr.ar_name = 0;
/*LINTED*/ /* MSG_INTL(EFMT_ARUNKNM) */
@@ -241,8 +243,16 @@ _elf_armem(Elf *elf, char *file, size_t fsz)
/*
* Initial archive processing
* An archive may have two special members.
- * A symbol table, named /, must be first if it is present.
- * A string table, named //, must precede all "normal" members.
+ *
+ * A symbol table, named / or /SYM64/, must be first if it is present.
+ * Both forms use the same layout differing in the width of the
+ * integer type used (32 or 64-bit respectively).
+ *
+ * A long name string table, named //, must precede all "normal"
+ * members. This string table is used to hold the names of archive
+ * members with names that are longer than 15 characters. It should not
+ * be confused with the string table found at the end of the symbol
+ * table, which is used to hold symbol names.
*
* This code "peeks" at headers but doesn't change them.
* Later processing wants original headers.
@@ -284,11 +294,12 @@ _elf_arinit(Elf * elf)
}
hdr = mem + sz;
- if (a->ar_name[1] == ' ') {
+ if (a->ar_name[1] == ' ') { /* 32-bit symbol table */
elf->ed_arsym = mem;
elf->ed_arsymsz = sz;
elf->ed_arsymoff = (char *)a - base;
} else if (a->ar_name[1] == '/' && a->ar_name[2] == ' ') {
+ /* Long name string table */
int k;
if (_elf_vm(elf, (size_t)(mem - elf->ed_ident),
@@ -314,6 +325,15 @@ _elf_arinit(Elf * elf)
++mem;
}
*(mem - 1) = '\0';
+ } else if (a->ar_name[1] == 'S' && a->ar_name[2] == 'Y' &&
+ a->ar_name[3] == 'M' && a->ar_name[4] == '6' &&
+ a->ar_name[5] == '4' && a->ar_name[6] == '/' &&
+ a->ar_name[7] == ' ') {
+ /* 64-bit symbol table */
+ elf->ed_arsym = mem;
+ elf->ed_arsymsz = sz;
+ elf->ed_arsymoff = (char *)a - base;
+ elf->ed_myflags |= EDF_ARSYM64;
} else {
return;
}
diff --git a/usr/src/cmd/sgs/libelf/common/decl.h b/usr/src/cmd/sgs/libelf/common/decl.h
index f293b14c42..613bfbba41 100644
--- a/usr/src/cmd/sgs/libelf/common/decl.h
+++ b/usr/src/cmd/sgs/libelf/common/decl.h
@@ -23,8 +23,7 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _DECL_H
@@ -391,6 +390,7 @@ NOTE(RWLOCK_COVERS_LOCKS(Elf::ed_rwlock, Elf_Scn::s_mutex))
#define EDF_MPROTECT 0x400 /* applies to slideable archives */
#define EDF_IMALLOC 0x800 /* wrimage dynamically allocated */
#define EDF_WRALLOC 0x1000 /* wrimage is to by dyn allocated */
+#define EDF_ARSYM64 0x2000 /* archive symbol table is 64-bit format */
typedef enum
diff --git a/usr/src/cmd/sgs/libelf/common/getarsym.c b/usr/src/cmd/sgs/libelf/common/getarsym.c
index 0163ef06ae..9431d75aa1 100644
--- a/usr/src/cmd/sgs/libelf/common/getarsym.c
+++ b/usr/src/cmd/sgs/libelf/common/getarsym.c
@@ -20,15 +20,12 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <errno.h>
#include <libelf.h>
@@ -38,40 +35,86 @@
/*
* Convert archive symbol table to memory format
- * This takes a pointer to file's archive symbol table,
- * alignment unconstrained. Returns null terminated
- * vector of Elf_Arsym structures.
*
- * Symbol table is the following:
- * # offsets 4-byte word
- * offset[0...] 4-byte word each
+ * This takes a pointer to file's archive symbol table, alignment
+ * unconstrained. Returns null terminated vector of Elf_Arsym
+ * structures. Elf_Arsym uses size_t to represent offsets, which
+ * will be 32-bit in 32-bit versions, and 64-bits otherwise.
+ *
+ * There are two forms of archive symbol table, the original 32-bit
+ * form, and a 64-bit form originally found in IRIX64. The two formats
+ * differ only in the width of the integer word:
+ *
+ * # offsets 4/8-byte word
+ * offset[0...] 4/8-byte word each
* strings null-terminated, for offset[x]
+ *
+ * By default, the 64-bit form is only used when the archive exceeds
+ * the limits of 32-bits (4GB) in size. However, this is not required,
+ * and the ar -S option can be used to create a 64-bit symbol table in
+ * an archive that is under 4GB.
+ *
+ * Both 32 and 64-bit versions of libelf can read the 32-bit format
+ * without loss of information. Similarly, a 64-bit version of libelf
+ * will have no problem reading a 64-bit symbol table. This leaves the
+ * case where a 32-bit libelf reads a 64-bit symbol table, which requires
+ * some explanation. The offsets in a 64-bit symbol table will have zeros
+ * in the upper half of the words until the size of the archive exceeds 4GB.
+ * However, 32-bit libelf is unable to read any files larger than 2GB
+ * (see comments in update.c). As such, any archive that the 32-bit version
+ * of this code will encounter will be under 4GB in size. The upper 4
+ * bytes of each word will be zero, and can be safely ignored.
*/
-#define get4(p) ((((((p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3])
-
+/*
+ * Offsets in archive headers are written in MSB (large endian) order
+ * on all platforms, regardless of native byte order. These macros read
+ * 4 and 8 byte values from unaligned memory.
+ *
+ * note:
+ * - The get8() macro for 32-bit code can ignore the first 4 bytes of
+ * of the word, because they are known to be 0.
+ *
+ * - The inner most value in these macros is cast to an unsigned integer
+ * of the final width in order to prevent the C comilier from doing
+ * unwanted sign extension when the topmost bit of a byte is set.
+ */
+#define get4(p) (((((((uint32_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3])
-static Elf_Void *arsym _((Byte *, size_t, size_t *));
+#ifdef _LP64
+#define get8(p) (((((((((((((((uint64_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+ \
+ p[3])<<8)+p[4])<<8)+p[5])<<8)+p[6])<<8)+p[7])
+#else
+#define get8(p) (((((((uint64_t)p[4]<<8)+p[5])<<8)+p[6])<<8)+p[7])
+#endif
-Elf_Void *
-arsym(Byte *off, size_t sz, size_t *e)
+static Elf_Void *
+arsym(Byte *off, size_t sz, size_t *e, int is64)
{
char *endstr = (char *)off + sz;
register char *str;
Byte *endoff;
Elf_Void *oas;
+ size_t eltsize = is64 ? 8 : 4;
{
register size_t n;
- if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) {
- _elf_seterr(EFMT_ARSYMSZ, 0);
- return (0);
+ if (is64) {
+ if (sz < 8 || (sz - 8) / 8 < (n = get8(off))) {
+ _elf_seterr(EFMT_ARSYMSZ, 0);
+ return (0);
+ }
+ } else {
+ if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) {
+ _elf_seterr(EFMT_ARSYMSZ, 0);
+ return (0);
+ }
}
- off += 4;
- endoff = off + n * 4;
+ off += eltsize;
+ endoff = off + n * eltsize;
/*
* string table must be present, null terminated
@@ -103,11 +146,14 @@ arsym(Byte *off, size_t sz, size_t *e)
free(oas);
return (0);
}
- as->as_off = get4(off);
+ if (is64)
+ as->as_off = get8(off);
+ else
+ as->as_off = get4(off);
as->as_name = str;
as->as_hash = elf_hash(str);
++as;
- off += 4;
+ off += eltsize;
while (*str++ != '\0')
/* LINTED */
;
@@ -126,10 +172,11 @@ elf_getarsym(Elf *elf, size_t *ptr)
Byte *as;
size_t sz;
Elf_Arsym *rc;
+ int is64;
if (ptr != 0)
*ptr = 0;
- if (elf == 0)
+ if (elf == NULL)
return (0);
ELFRLOCK(elf);
if (elf->ed_kind != ELF_K_AR) {
@@ -148,6 +195,8 @@ elf_getarsym(Elf *elf, size_t *ptr)
/* LINTED */
return ((Elf_Arsym *)as);
}
+ is64 = (elf->ed_myflags & EDF_ARSYM64) != 0;
+
/*
* We're gonna need a write lock.
*/
@@ -159,7 +208,7 @@ elf_getarsym(Elf *elf, size_t *ptr)
ELFUNLOCK(elf);
return (0);
}
- if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz)) == 0) {
+ if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz, is64)) == 0) {
ELFUNLOCK(elf);
return (0);
}
@@ -170,3 +219,32 @@ elf_getarsym(Elf *elf, size_t *ptr)
ELFUNLOCK(elf);
return (rc);
}
+
+/*
+ * Private function to obtain the value sizeof() would return
+ * for a word from the symbol table from the given archive. Normally,
+ * this is an unimportant implementation detail hidden within
+ * elf_getarsym(). However, it is useful to elfdump for formatting the
+ * output correctly, and for the file command.
+ *
+ * exit:
+ * Returns 4 (32-bit) or 8 (64-bit) if a symbol table is present.
+ * Returns 0 in all other cases.
+ */
+size_t
+_elf_getarsymwordsize(Elf *elf)
+{
+ size_t size;
+
+ if (elf == NULL)
+ return (0);
+
+ ELFRLOCK(elf);
+ if ((elf->ed_kind == ELF_K_AR) && (elf->ed_arsym != 0))
+ size = (elf->ed_myflags & EDF_ARSYM64) ? 8 : 4;
+ else
+ size = 0;
+ ELFUNLOCK(elf);
+
+ return (size);
+}
diff --git a/usr/src/cmd/sgs/libelf/common/llib-lelf b/usr/src/cmd/sgs/libelf/common/llib-lelf
index 19f99fcc47..f525dde839 100644
--- a/usr/src/cmd/sgs/libelf/common/llib-lelf
+++ b/usr/src/cmd/sgs/libelf/common/llib-lelf
@@ -143,6 +143,7 @@ int nlist(const char *, struct nlist *);
*/
extern void _elf_execfill(_elf_execfill_func_t *);
extern off_t _elf_getarhdrbase(Elf *);
+extern size_t _elf_getarsymwordsize(Elf *);
extern size_t _elf_getnextoff(Elf *);
Elf64_Off _elf_getxoff(Elf_Data *);
int _elf_swap_wrimage(Elf *);
diff --git a/usr/src/cmd/sgs/libelf/common/mapfile-vers b/usr/src/cmd/sgs/libelf/common/mapfile-vers
index 6c46234e31..35f397f126 100644
--- a/usr/src/cmd/sgs/libelf/common/mapfile-vers
+++ b/usr/src/cmd/sgs/libelf/common/mapfile-vers
@@ -163,6 +163,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
global:
_elf_execfill;
_elf_getarhdrbase;
+ _elf_getarsymwordsize;
_elf_getnextoff;
_elf_getxoff;
_elf_outsync;
diff --git a/usr/src/cmd/sgs/mcs/common/file.c b/usr/src/cmd/sgs/mcs/common/file.c
index 2d9eca56b9..7fbf0af943 100644
--- a/usr/src/cmd/sgs/mcs/common/file.c
+++ b/usr/src/cmd/sgs/mcs/common/file.c
@@ -23,8 +23,7 @@
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <errno.h>
@@ -1338,7 +1337,8 @@ copy_non_elf_to_temp_ar(
char mem_header_buf[sizeof (struct ar_hdr) + 1];
char *file_buf;
- if (strcmp(mem_header->ar_name, "/") != 0) {
+ if ((strcmp(mem_header->ar_name, "/") != 0) &&
+ (strcmp(mem_header->ar_name, "/SYM64/") != 0)) {
(void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname,
mem_header->ar_date, (unsigned)mem_header->ar_uid,
(unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode,
diff --git a/usr/src/cmd/sgs/messages/Makefile.com b/usr/src/cmd/sgs/messages/Makefile.com
index 97b2c0c7e3..8a57a7094b 100644
--- a/usr/src/cmd/sgs/messages/Makefile.com
+++ b/usr/src/cmd/sgs/messages/Makefile.com
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
#
# cmd/sgs/messages/Makefile.com
@@ -44,7 +43,8 @@ MSGFMT= msgfmt
POFILES= ld ldd libld liblddbg \
librtld rtld libelf ldprof \
libcrle crle moe pvs \
- elfdump elfedit elfwrap lari
+ elfdump elfedit elfwrap lari \
+ ar
# These message files are generated as a side effect of generating the
# elfedit messages. Otherwise they are the same thing as POFILES
diff --git a/usr/src/cmd/sgs/messages/sgs.ident b/usr/src/cmd/sgs/messages/sgs.ident
index eaee78733e..9aa369693f 100644
--- a/usr/src/cmd/sgs/messages/sgs.ident
+++ b/usr/src/cmd/sgs/messages/sgs.ident
@@ -1,6 +1,5 @@
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
#
# CDDL HEADER START
#
@@ -58,3 +57,4 @@ MSG_ID_ELFEDIT_STR 27 SUNW_OST_SGS /* str: */
MSG_ID_ELFEDIT_SYM 27 SUNW_OST_SGS /* sym: */
MSG_ID_ELFEDIT_SYMINFO 27 SUNW_OST_SGS /* syminfo: */
MSG_ID_ELFWRAP 28 SUNW_OST_SGS /* sgs/elfwrap */
+MSG_ID_AR 29 SUNW_OST_SGS /* sgs/ar */
diff --git a/usr/src/cmd/sgs/nm/common/nm.c b/usr/src/cmd/sgs/nm/common/nm.c
index d8d1c7cddd..258bd9fd67 100644
--- a/usr/src/cmd/sgs/nm/common/nm.c
+++ b/usr/src/cmd/sgs/nm/common/nm.c
@@ -609,7 +609,7 @@ print_ar_files(int fd, Elf * elf_file, char *filename)
prog_name, filename, elf_errmsg(-1));
return;
}
- if ((int)strncmp(p_ar->ar_name, "/", 1) == 0) {
+ if (p_ar->ar_name[0] == '/') {
cmd = elf_next(arf);
(void) elf_end(arf);
continue;
diff --git a/usr/src/cmd/sgs/nm/i386/Makefile b/usr/src/cmd/sgs/nm/i386/Makefile
index 3a4112fb12..6653481253 100644
--- a/usr/src/cmd/sgs/nm/i386/Makefile
+++ b/usr/src/cmd/sgs/nm/i386/Makefile
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
#
# cmd/sgs/nm/i386/Makefile
#
@@ -53,13 +52,6 @@ objs.xpg4/%.o := CPPFLAGS += -DXPG4
$(DEMOBJS):= DEFLIST = -DELF_OBJ
-# Building SUNWonld results in a call to the `package' target. Requirements
-# needed to run this application on older releases are established:
-# i18n support requires libintl.so.1 prior to 2.6
-
-package := LDLIBS += /usr/lib/libintl.so.1
-
-
objs.xpg4/%.o: ../common/%.c
$(COMPILE.c) -o $@ $<
diff --git a/usr/src/cmd/sgs/packages/Makefile b/usr/src/cmd/sgs/packages/Makefile
index f990d328a9..2a70f64d62 100644
--- a/usr/src/cmd/sgs/packages/Makefile
+++ b/usr/src/cmd/sgs/packages/Makefile
@@ -20,8 +20,7 @@
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
#
include $(SRC)/Makefile.master
@@ -76,6 +75,7 @@ PKGDIRS= ../libcrle \
../elfedit \
../elfedit/modules \
../elfwrap \
+ ../ar \
../crle \
../dump \
../lari \
diff --git a/usr/src/cmd/sgs/packages/Makefile.com b/usr/src/cmd/sgs/packages/Makefile.com
index 4512a20777..714a8f010f 100644
--- a/usr/src/cmd/sgs/packages/Makefile.com
+++ b/usr/src/cmd/sgs/packages/Makefile.com
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
#
include $(SRC)/Makefile.master
@@ -28,7 +27,7 @@ include $(SRC)/Makefile.master
LINTLOG= ../lint.$(MACH).log
PKGARCHIVE= .
-DATAFILES= admin copyright prototype_com prototype_$(MACH) postinstall \
+DATAFILES= copyright prototype_com prototype_$(MACH) postinstall \
preremove depend checkinstall
README= SUNWonld-README
FILES= $(DATAFILES) pkginfo
diff --git a/usr/src/cmd/sgs/packages/Makefile.lint b/usr/src/cmd/sgs/packages/Makefile.lint
index a5122dc95a..09db2eb0ed 100644
--- a/usr/src/cmd/sgs/packages/Makefile.lint
+++ b/usr/src/cmd/sgs/packages/Makefile.lint
@@ -20,10 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
#
# cmd/sgs/packages/Makefile.lint
@@ -60,6 +57,7 @@ LINTLDIRS= ../libld \
../elfedit \
../elfedit/modules \
../elfwrap \
+ ../ar \
../crle \
../dump \
../ld \
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index eaeb3372ff..74e1fb4c7a 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1601,3 +1601,5 @@ Bugid Risk Synopsis
6962343 sgsmsg should use mkstemp() for temporary file creation
6965723 libsoftcrypto symbol capabilities rely on compiler generated
capabilities - gcc failure (link-editor components only)
+6952219 ld support for archives larger than 2 GB (D, P)
+ PSARC/2010/224 Support for archives larger than 2 GB
diff --git a/usr/src/cmd/sgs/packages/common/prototype_com b/usr/src/cmd/sgs/packages/common/prototype_com
index 76bda331a6..b16d52eba4 100644
--- a/usr/src/cmd/sgs/packages/common/prototype_com
+++ b/usr/src/cmd/sgs/packages/common/prototype_com
@@ -20,10 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
@@ -62,6 +59,9 @@ f none $SGSDIR/lib/librtld.so.1=lib/librtld.so.1 755 root bin
s none $SGSDIR/lib/librtld_db.so=librtld_db.so.1
f none $SGSDIR/lib/librtld_db.so.1=lib/librtld_db.so.1 755 root bin
d none $SGSDIR/usr/bin 755 root bin
+f none $SGSDIR/usr/bin/ar=usr/bin/ar 555 root bin
+s none $SGSDIR/usr/ccs/bin/ar=../../bin/ar
+f none $SGSDIR/usr/xpg4/bin/ar=usr/xpg4/bin/ar 0555 root bin
f none $SGSDIR/usr/bin/crle=usr/bin/crle 555 root bin
f none $SGSDIR/usr/bin/ldd=usr/bin/ldd 555 root bin
f none $SGSDIR/usr/bin/moe=usr/bin/moe 555 root bin
@@ -247,10 +247,6 @@ f none opt/SUNWonld/man/man1l/sgsmsg.1l 444 root bin
#d none $SGSDIR/usr/share/lib 755 root bin
#d none $SGSDIR/usr/share/lib/ccs 755 root bin
-#f none $SGSDIR/usr/bin/ar=usr/bin/ar 555 root bin
-#s none $SGSDIR/usr/ccs/bin/ar=../../bin/ar
-#f none $SGSDIR/usr/xpg4/bin/ar=usr/xpg4/bin/ar 0555 root bin
-
#f none $SGSDIR/usr/bin/error=usr/bin/error 555 root bin
#s none $SGSDIR/usr/ccs/bin/error=../../bin/error
diff --git a/usr/src/cmd/sgs/packages/common/prototype_i386 b/usr/src/cmd/sgs/packages/common/prototype_i386
index 52b1ed359c..b17f7b4a46 100644
--- a/usr/src/cmd/sgs/packages/common/prototype_i386
+++ b/usr/src/cmd/sgs/packages/common/prototype_i386
@@ -20,10 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
@@ -50,6 +47,8 @@ f none $SGSDIR/lib/amd64/librtld.so.1=lib/amd64/librtld.so.1 755 root bin
f none $SGSDIR/lib/amd64/librtld_db.so.1=lib/amd64/librtld_db.so.1 755 root bin
s none $SGSDIR/lib/amd64/librtld_db.so=librtld_db.so.1
d none $SGSDIR/usr/bin/amd64 755 root bin
+f none $SGSDIR/usr/bin/amd64/ar=usr/bin/amd64/ar 555 root bin
+s none $SGSDIR/usr/ccs/bin/amd64/ar=../../bin/amd64/ar
f none $SGSDIR/usr/bin/amd64/crle=usr/bin/amd64/crle 555 root bin
f none $SGSDIR/usr/bin/amd64/ldd=usr/bin/amd64/ldd 555 root bin
f none $SGSDIR/usr/bin/amd64/moe=usr/bin/amd64/moe 555 root bin
diff --git a/usr/src/cmd/sgs/packages/common/prototype_sparc b/usr/src/cmd/sgs/packages/common/prototype_sparc
index cd676819c6..6f6e6f317c 100644
--- a/usr/src/cmd/sgs/packages/common/prototype_sparc
+++ b/usr/src/cmd/sgs/packages/common/prototype_sparc
@@ -20,10 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
@@ -50,6 +47,8 @@ f none $SGSDIR/lib/sparcv9/librtld.so.1=lib/sparcv9/librtld.so.1 755 root bin
f none $SGSDIR/lib/sparcv9/librtld_db.so.1=lib/sparcv9/librtld_db.so.1 755 root bin
s none $SGSDIR/lib/sparcv9/librtld_db.so=librtld_db.so.1
d none $SGSDIR/usr/bin/sparcv9 755 root bin
+f none $SGSDIR/usr/bin/sparcv9/ar=usr/bin/sparcv9/ar 555 root bin
+s none $SGSDIR/usr/ccs/bin/sparcv9/ar=../../bin/sparcv9/ar
f none $SGSDIR/usr/bin/sparcv9/crle=usr/bin/sparcv9/crle 555 root bin
f none $SGSDIR/usr/bin/sparcv9/ldd=usr/bin/sparcv9/ldd 555 root bin
f none $SGSDIR/usr/bin/sparcv9/moe=usr/bin/sparcv9/moe 555 root bin
diff --git a/usr/src/pkg/manifests/developer-object-file.mf b/usr/src/pkg/manifests/developer-object-file.mf
index 4b662ee421..a9d010062b 100644
--- a/usr/src/pkg/manifests/developer-object-file.mf
+++ b/usr/src/pkg/manifests/developer-object-file.mf
@@ -43,6 +43,7 @@ dir path=usr/lib/elfedit/$(ARCH64)
dir path=usr/share group=sys
dir path=usr/share/lib group=sys
dir path=usr/share/lib/ccs
+file path=usr/bin/$(ARCH64)/ar mode=0555
file path=usr/bin/$(ARCH64)/dump mode=0555
file path=usr/bin/$(ARCH64)/elfdump mode=0555
file path=usr/bin/$(ARCH64)/elfedit mode=0555
@@ -108,6 +109,7 @@ license cmd/backup/dump/THIRDPARTYLICENSE \
license=cmd/backup/dump/THIRDPARTYLICENSE
license cr_Sun license=cr_Sun
license lic_CDDL license=lic_CDDL
+link path=usr/ccs/bin/$(ARCH64)/ar target=../../../bin/$(ARCH64)/ar
link path=usr/ccs/bin/$(ARCH64)/dump target=../../../bin/$(ARCH64)/dump
link path=usr/ccs/bin/$(ARCH64)/elfdump target=../../../bin/$(ARCH64)/elfdump
link path=usr/ccs/bin/$(ARCH64)/mcs target=../../../bin/$(ARCH64)/mcs