diff --git a/MAINTAINERS b/MAINTAINERS index 29236caf6b25..7e6610f376e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -48,7 +48,6 @@ cd(4) ken Pre-commit review requested. pass(4) ken Pre-commit review requested. ch(4) ken Pre-commit review requested. em(4) jfv Pre-commit review requested. -tdfx(4) cokane Just keep me informed of changes, try not to break it. sendmail gshapiro Pre-commit review requested. etc/mail gshapiro Pre-commit review requested. Keep in sync with -STABLE. @@ -118,7 +117,6 @@ lib/libc/stdtime edwin Heads-up appreciated, since parts of this code is maintained by a third party source. sbin/routed bms Pre-commit review; notify vendor at rhyolite.com isci(4) jimharris Pre-commit review requested. -3dfx cokane Pre-commit review preferred. cmx daniel@roe.ch Pre-commit review preferred. filemon obrien Pre-commit review preferred. sysdoc trhodes Pre-commit review preferred. diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 1d7dc8686e84..c0461cff4e88 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,12 @@ # xargs -n1 | sort | uniq -d; # done +# 20141126: convert sbin/mdconfig/tests to ATF format tests +OLD_FILES+=usr/tests/sbin/mdconfig/legacy_test +OLD_FILES+=usr/tests/sbin/mdconfig/mdconfig.test +OLD_FILES+=usr/tests/sbin/mdconfig/run.pl +# 20141126: remove xform_ipip decapsulation fallback +OLD_FILES+=usr/include/netipsec/ipip_var.h # 20141109: faith/faithd removal OLD_FILES+=etc/rc.d/faith OLD_FILES+=usr/share/man/man4/faith.4.gz @@ -134,10 +140,12 @@ OLD_FILES+=usr/include/readline/chardefs.h OLD_FILES+=usr/include/readline/history.h OLD_FILES+=usr/include/readline/keymaps.h OLD_FILES+=usr/include/readline/readline.h +OLD_FILES+=usr/include/readline/tilde.h OLD_FILES+=usr/include/readline/rlconf.h OLD_FILES+=usr/include/readline/rlstdc.h OLD_FILES+=usr/include/readline/rltypedefs.h OLD_FILES+=usr/include/readline/rltypedefs.h +OLD_DIRS+=usr/include/readline OLD_FILES+=usr/share/info/readline.info.gz OLD_FILES+=usr/share/man/man3/readline.3.gz # 20140625: csup removal diff --git a/bin/csh/Makefile b/bin/csh/Makefile index fd345245eb0b..e3df1d464193 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -40,8 +40,7 @@ MLINKS= csh.1 tcsh.1 # utilities of the same name are handled with the associated manpage, # builtin.1 in share/man/man1/. -DPADD= ${LIBTERMCAPW} ${LIBCRYPT} -LDADD= -ltermcapw -lcrypt +LIBADD= termcapw crypt LINKS= ${BINDIR}/csh ${BINDIR}/tcsh diff --git a/bin/df/Makefile b/bin/df/Makefile index fb7b09a6ffe8..5cdae9ed7d2b 100644 --- a/bin/df/Makefile +++ b/bin/df/Makefile @@ -9,7 +9,6 @@ SRCS= df.c vfslist.c CFLAGS+= -I${MOUNT} -DPADD= ${LIBUTIL} ${LIBXO} -LDADD= -lutil -lxo +LIBADD= xo util .include diff --git a/bin/ed/Makefile b/bin/ed/Makefile index cc47a4271e92..bef3ff1ad5ef 100644 --- a/bin/ed/Makefile +++ b/bin/ed/Makefile @@ -9,8 +9,7 @@ MLINKS= ed.1 red.1 .if ${MK_OPENSSL} != "no" && ${MK_ED_CRYPTO} != "no" CFLAGS+=-DDES -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +LIBADD= crypto .endif .include diff --git a/bin/ls/Makefile b/bin/ls/Makefile index dce204655be0..58206e0884cc 100644 --- a/bin/ls/Makefile +++ b/bin/ls/Makefile @@ -5,14 +5,12 @@ PROG= ls SRCS= cmp.c ls.c print.c util.c -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .if !defined(RELEASE_CRUNCH) && \ ${MK_LS_COLORS} != no CFLAGS+= -DCOLORLS -DPADD+= ${LIBTERMCAPW} -LDADD+= -ltermcapw +LIBADD+= termcapw .endif .include diff --git a/bin/pkill/Makefile b/bin/pkill/Makefile index 11bfbe329596..84a5af71ddf3 100644 --- a/bin/pkill/Makefile +++ b/bin/pkill/Makefile @@ -5,8 +5,7 @@ PROG= pkill -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm LINKS= ${BINDIR}/pkill ${BINDIR}/pgrep MLINKS= pkill.1 pgrep.1 diff --git a/bin/ps/Makefile b/bin/ps/Makefile index 5ba4f2fa705b..30dbdc9c360e 100644 --- a/bin/ps/Makefile +++ b/bin/ps/Makefile @@ -11,7 +11,6 @@ SRCS= fmt.c keyword.c nlist.c print.c ps.c # on large systems. # CFLAGS+=-DLAZY_PS -DPADD= ${LIBM} ${LIBKVM} ${LIBJAIL} -LDADD= -lm -lkvm -ljail +LIBADD= m kvm jail .include diff --git a/bin/rmail/Makefile b/bin/rmail/Makefile index ad788a4745a8..a74898f853c7 100644 --- a/bin/rmail/Makefile +++ b/bin/rmail/Makefile @@ -14,11 +14,7 @@ MAN= rmail.8 WARNS?= 2 CFLAGS+=-I${SENDMAIL_DIR}/include -I. -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -DPADD= ${LIBSM} -LDADD= ${LIBSM} +LIBADD= sm SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/bin/sh/Makefile b/bin/sh/Makefile index ad43d33e6c3c..3f28a1231fd3 100644 --- a/bin/sh/Makefile +++ b/bin/sh/Makefile @@ -18,8 +18,7 @@ SRCS= ${SHSRCS} ${GENSRCS} ${GENHDRS} # utilities of the same name are handled with the associated manpage, # builtin.1 in share/man/man1/. -DPADD= ${LIBEDIT} ${LIBTERMCAPW} -LDADD= -ledit -ltermcapw +LIBADD= edit CFLAGS+=-DSHELL -I. -I${.CURDIR} # for debug: diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c index e3905c1ff45a..9dd52b53263d 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c @@ -1211,13 +1211,13 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) #if defined(__FreeBSD__) if (sh.sh_size == 0) continue; - if (is_elf_obj && (sh.sh_type == SHT_PROGBITS || - sh.sh_type == SHT_NOBITS)) { + if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) { alignmask = sh.sh_addralign - 1; mapbase += alignmask; mapbase &= ~alignmask; sh.sh_addr = mapbase; - dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr; + if (is_elf_obj) + dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr; mapbase += sh.sh_size; } #endif diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c index 6acb86b155ba..cd8ceb655934 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c @@ -545,8 +545,9 @@ dt_probe_define(dt_provider_t *pvp, dt_probe_t *prp, for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { if (strcmp(pip->pi_fname, fname) == 0 && - ((rname == NULL && pip->pi_rname[0] == '\0') || - (rname != NULL && strcmp(pip->pi_rname, rname)) == 0)) + ((rname == NULL && pip->pi_rname == NULL) || + (rname != NULL && pip->pi_rname != NULL && + strcmp(pip->pi_rname, rname) == 0))) break; } diff --git a/contrib/elftoolchain/addr2line/Makefile b/contrib/elftoolchain/addr2line/Makefile new file mode 100644 index 000000000000..e388bc0a6edb --- /dev/null +++ b/contrib/elftoolchain/addr2line/Makefile @@ -0,0 +1,15 @@ +# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $ + +TOP= .. + +PROG= addr2line +SRCS= addr2line.c + +WARNS?= 6 + +DPADD= ${LIBELF} ${LIBELFTC} ${LIBDWARF} +LDADD= -lelftc -ldwarf -lelf + +MAN1= addr2line.1 + +.include "${TOP}/mk/elftoolchain.prog.mk" diff --git a/contrib/elftoolchain/addr2line/addr2line.1 b/contrib/elftoolchain/addr2line/addr2line.1 new file mode 100644 index 000000000000..98edda50fb13 --- /dev/null +++ b/contrib/elftoolchain/addr2line/addr2line.1 @@ -0,0 +1,159 @@ +.\" Copyright (c) 2009,2010 Joseph Koshy +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer +.\" in this position and unchanged. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: addr2line.1 2066 2011-10-26 15:40:28Z jkoshy $ +.\" +.Dd July 25, 2010 +.Os +.Dt ADDR2LINE 1 +.Sh NAME +.Nm addr2line +.Nd translate program addresses to source file names and line numbers +.Sh SYNOPSIS +.Nm +.Op Fl b Ar target | Fl -target Ns = Ns Ar target +.Op Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname +.Op Fl f | Fl -functions +.Op Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname +.Op Fl s | Fl -basename +.Op Fl C | Fl -demangle +.Op Fl H | Fl -help +.Op Fl V | Fl -version +.Op Ar hexaddress Ns ... +.Sh DESCRIPTION +The +.Nm +utility translates program addresses specified by the command line +arguments +.Ar hexaddress +to their corresponding source file names and line numbers. +If no arguments are given to +.Nm , +it will read these addresses from standard input. +.Pp +Program addresses specified by arguments +.Ar hexaddress +are encoded using the conventions accepted by +.Xr strtoull 3 . +.Pp +By default, +.Nm +will use the executable +.Dq Pa a.out . +The +.Fl e +option may be used to specified a different ELF object. +.Pp +The +.Nm +utility recognizes the following options: +.Bl -tag -width indent +.It Fl b Ar target | Fl -target Ns = Ns Ar target +This option is recognized by +.Nm +but is ignored. +It is supported for compatibility with GNU binutils. +.It Fl e Ar pathname | Fl -exe Ns = Ns Ar pathname +Use the ELF object specified by argument +.Ar pathname +to translate addresses. +If this option is not specified, +.Nm +will use the file +.Dq Pa a.out . +.It Fl f | Fl -functions +Display function names in addition to file and line number information. +.It Fl j Ar sectionname | Fl -section Ns = Ns Ar sectionname +The values specified by arguments +.Ar hexaddress +are to be treated as offsets into the section named +.Ar sectionname . +.It Fl s | -basename +Display only the base name for each file name. +.It Fl C | Fl -demangle +Demangle C++ names. +.It Fl H | Fl -help +Print a help message. +.It Fl V | Fl -version +Print a version identifier and exit. +.El +.Sh OUTPUT FORMAT +If the +.Fl f +option was not specified, +.Nm +will print the file name and line number for each address specified +on a separate line. +.Pp +If the +.Fl f +option was specified, +.Nm +will print a line containing the name of the function corresponding +to program address +.Ar hexaddress , +followed by a line with the file name and line number. +.Pp +The +.Nm +utility prints the file name and line number using the format +.Dq FILENAME:LINENUMBER . +.Pp +If a file or function name could not be determined, +.Nm +will print a question mark in their place. +If the line number could not be determined, +.Nm +will print a zero in its place. +.Sh EXAMPLES +To map address 080483c4 in the default executable +.Pa a.out +to a source file name and line number use: +.D1 "% addr2line 080483c4" +.Pp +To map address 080483c4 in executable +.Pa helloworld , +use: +.D1 "% addr2line -e helloworld 080483c4" +.Pp +To have +.Nm +act as a filter reading addresses from its standard input use: +.D1 "% addr2line" +.Pp +To print the function name corresponding to an address in addition to +its source file and line number use: +.D1 "% addr2line -f 080483c4" +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr nm 1 , +.Xr elfdump 1 , +.Xr elfcopy 1 , +.Xr strtoull 3 +.Sh AUTHORS +The +.Nm +utility was written by +.An "Kai Wang" Aq kaiwang27@users.sourceforge.net . diff --git a/contrib/elftoolchain/addr2line/addr2line.c b/contrib/elftoolchain/addr2line/addr2line.c new file mode 100644 index 000000000000..b58b4b352a47 --- /dev/null +++ b/contrib/elftoolchain/addr2line/addr2line.c @@ -0,0 +1,410 @@ +/*- + * Copyright (c) 2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: addr2line.c 2185 2011-11-19 16:07:16Z jkoshy $"); + +static struct option longopts[] = { + {"target" , required_argument, NULL, 'b'}, + {"demangle", no_argument, NULL, 'C'}, + {"exe", required_argument, NULL, 'e'}, + {"functions", no_argument, NULL, 'f'}, + {"section", required_argument, NULL, 'j'}, + {"basename", no_argument, NULL, 's'}, + {"help", no_argument, NULL, 'H'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} +}; +static int demangle, func, base; +static char unknown[] = { '?', '?', '\0' }; +static Dwarf_Addr section_base; + +#define USAGE_MESSAGE "\ +Usage: %s [options] hexaddress...\n\ + Map program addresses to source file names and line numbers.\n\n\ + Options:\n\ + -b TGT | --target=TGT (Accepted but ignored).\n\ + -e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\ + -f | --functions Display function names.\n\ + -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ + -s | --basename Only show the base name for each file name.\n\ + -C | --demangle Demangle C++ names.\n\ + -H | --help Print a help message.\n\ + -V | --version Print a version identifier and exit.\n" + +static void +usage(void) +{ + (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(1); +} + +static void +version(void) +{ + + fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); + exit(0); +} + +static void +search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, + const char **rlt_func) +{ + Dwarf_Die ret_die, spec_die; + Dwarf_Error de; + Dwarf_Half tag; + Dwarf_Unsigned lopc, hipc; + Dwarf_Off ref; + Dwarf_Attribute sub_at, spec_at; + char *func0; + int ret; + + if (*rlt_func != NULL) + return; + + if (dwarf_tag(die, &tag, &de)) { + warnx("dwarf_tag: %s", dwarf_errmsg(de)); + goto cont_search; + } + if (tag == DW_TAG_subprogram) { + if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || + dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) + goto cont_search; + if (addr < lopc || addr >= hipc) + goto cont_search; + + /* Found it! */ + + *rlt_func = unknown; + ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); + if (ret == DW_DLV_ERROR) + return; + if (ret == DW_DLV_OK) { + if (dwarf_formstring(sub_at, &func0, &de)) + *rlt_func = unknown; + else + *rlt_func = func0; + return; + } + + /* + * If DW_AT_name is not present, but DW_AT_specification is + * present, then probably the actual name is in the DIE + * referenced by DW_AT_specification. + */ + if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) + return; + if (dwarf_global_formref(spec_at, &ref, &de)) + return; + if (dwarf_offdie(dbg, ref, &spec_die, &de)) + return; + if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) + *rlt_func = unknown; + + return; + } + +cont_search: + + /* Search children. */ + ret = dwarf_child(die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_func(dbg, ret_die, addr, rlt_func); + + /* Search sibling. */ + ret = dwarf_siblingof(dbg, die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_func(dbg, ret_die, addr, rlt_func); +} + +static void +translate(Dwarf_Debug dbg, const char* addrstr) +{ + Dwarf_Die die; + Dwarf_Line *lbuf; + Dwarf_Error de; + Dwarf_Half tag; + Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; + Dwarf_Signed lcount; + Dwarf_Addr lineaddr, plineaddr; + const char *funcname; + char *file, *file0, *pfile; + char demangled[1024]; + int i, ret; + + addr = strtoull(addrstr, NULL, 16); + addr += section_base; + lineno = 0; + file = unknown; + + while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, + &de)) == DW_DLV_OK) { + die = NULL; + while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", + dwarf_errmsg(de)); + goto out; + } + /* XXX: What about DW_TAG_partial_unit? */ + if (tag == DW_TAG_compile_unit) + break; + } + if (die == NULL) { + warnx("could not find DW_TAG_compile_unit die"); + goto out; + } + if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && + !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { + /* + * Check if the address falls into the PC range of + * this CU. + */ + if (addr < lopc || addr >= hipc) + continue; + } + + if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { + warnx("dwarf_srclines: %s", dwarf_errmsg(de)); + goto out; + } + + plineaddr = ~0ULL; + plineno = 0; + pfile = unknown; + for (i = 0; i < lcount; i++) { + if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { + warnx("dwarf_lineaddr: %s", + dwarf_errmsg(de)); + goto out; + } + if (dwarf_lineno(lbuf[i], &lineno, &de)) { + warnx("dwarf_lineno: %s", + dwarf_errmsg(de)); + goto out; + } + if (dwarf_linesrc(lbuf[i], &file0, &de)) { + warnx("dwarf_linesrc: %s", + dwarf_errmsg(de)); + } else + file = file0; + if (addr == lineaddr) + goto out; + else if (addr < lineaddr && addr > plineaddr) { + lineno = plineno; + file = pfile; + goto out; + } + plineaddr = lineaddr; + plineno = lineno; + pfile = file; + } + } + +out: + funcname = NULL; + if (ret == DW_DLV_OK && func) + search_func(dbg, die, addr, &funcname); + + if (func) { + if (funcname == NULL) + funcname = unknown; + if (demangle && + !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) + printf("%s\n", demangled); + else + printf("%s\n", funcname); + } + + (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); + + /* + * Reset internal CU pointer, so we will start from the first CU + * next round. + */ + while (ret != DW_DLV_NO_ENTRY) { + if (ret == DW_DLV_ERROR) + errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", + dwarf_errmsg(de)); + ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, + &de); + } +} + +static void +find_section_base(const char *exe, Elf *e, const char *section) +{ + Dwarf_Addr off; + Elf_Scn *scn; + GElf_Ehdr eh; + GElf_Shdr sh; + size_t shstrndx; + int elferr; + const char *name; + + if (gelf_getehdr(e, &eh) != &eh) { + warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); + return; + } + + if (!elf_getshstrndx(e, &shstrndx)) { + warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); + return; + } + + (void) elf_errno(); + off = 0; + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + continue; + } + if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) + goto next; + if (!strcmp(section, name)) { + if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { + /* + * For executables, section base is the virtual + * address of the specified section. + */ + section_base = sh.sh_addr; + } else if (eh.e_type == ET_REL) { + /* + * For relocatables, section base is the + * relative offset of the specified section + * to the start of the first section. + */ + section_base = off; + } else + warnx("unknown e_type %u", eh.e_type); + return; + } + next: + off += sh.sh_size; + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); +} + +int +main(int argc, char **argv) +{ + Elf *e; + Dwarf_Debug dbg; + Dwarf_Error de; + const char *exe, *section; + char line[1024]; + int fd, i, opt; + + exe = NULL; + section = NULL; + while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != + -1) { + switch (opt) { + case 'b': + /* ignored */ + break; + case 'C': + demangle = 1; + break; + case 'e': + exe = optarg; + break; + case 'f': + func = 1; + break; + case 'j': + section = optarg; + break; + case 's': + base = 1; + break; + case 'H': + usage(); + case 'V': + version(); + default: + usage(); + } + } + + argv += optind; + argc -= optind; + + if (exe == NULL) + exe = "a.out"; + + if ((fd = open(exe, O_RDONLY)) < 0) + err(EXIT_FAILURE, "%s", exe); + + if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) + errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); + + if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) + errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); + + if (section) + find_section_base(exe, e, section); + else + section_base = 0; + + if (argc > 0) + for (i = 0; i < argc; i++) + translate(dbg, argv[i]); + else + while (fgets(line, sizeof(line), stdin) != NULL) + translate(dbg, line); + + dwarf_finish(dbg, &de); + + (void) elf_end(e); + + exit(0); +} diff --git a/contrib/elftoolchain/cxxfilt/Makefile b/contrib/elftoolchain/cxxfilt/Makefile new file mode 100644 index 000000000000..ca50f91face8 --- /dev/null +++ b/contrib/elftoolchain/cxxfilt/Makefile @@ -0,0 +1,15 @@ +# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $ + +TOP= .. + +PROG= c++filt +SRCS= cxxfilt.c + +WARNS?= 6 + +DPADD= ${LIBELFTC} ${LIBELF} +LDADD= -lelftc -lelf + +MAN1= c++filt.1 + +.include "${TOP}/mk/elftoolchain.prog.mk" diff --git a/contrib/elftoolchain/cxxfilt/c++filt.1 b/contrib/elftoolchain/cxxfilt/c++filt.1 new file mode 100644 index 000000000000..0a123c773c33 --- /dev/null +++ b/contrib/elftoolchain/cxxfilt/c++filt.1 @@ -0,0 +1,109 @@ +.\" Copyright (c) 2009-2011 Joseph Koshy +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer +.\" in this position and unchanged. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: c++filt.1 2175 2011-11-16 05:51:49Z jkoshy $ +.\" +.Dd August 24, 2011 +.Os +.Dt C++FILT 1 +.Sh NAME +.Nm c++filt +.Nd decode C++ symbols +.Sh SYNOPSIS +.Nm +.Op Fl -help +.Op Fl _ | Fl -strip-underscores +.Op Fl n | Fl -no-strip-underscores +.Op Fl p | Fl -no-params +.Op Fl s Ar scheme | Fl -format Ns = Ns Ar scheme +.Op Fl V | Fl -version +.Op Ar encoded-names ... +.Sh DESCRIPTION +The +.Nm +utility translates encoded C++ symbol names to human-readable form. +.Pp +The +.Nm +utility has two operating modes. +.Bl -bullet +.It +If arguments +.Ar encoded-names +are not specified, then +.Nm +will act as a filter, reading from standard input +and writing to standard output. +.It +If arguments +.Ar encoded-names +are specified, then +.Nm +will decode each such argument in turn, writing its decoded form +to standard output. +.El +.Pp +The +.Nm +utility recognizes the following options: +.Bl -tag -width indent +.It Fl -help +Print a help message and exit. +.It Fl _ | Fl -strip-underscores +Remove a leading underscore from symbol names prior to decoding them. +.It Fl n | Fl -no-strip-underscores +Do not remove leading underscores from names. +.It Fl p | Fl -no-params +This option is recognized but ignored. +.It Fl s Ar scheme | Fl -format Ns = Ns Ar scheme +Select the encoding scheme to use. +Argument +.Ar scheme +can be one of the following: +.Bl -tag -width "gnu-v5" +.It Ar arm +Use the encoding scheme specified by the C++ Annotated Reference Manual. +.It Ar auto +Guess the encoding scheme from the input. +.It Ar gnu +Use the encoding scheme used by the GNU C++ compiler. +.It Ar gnu-v3 +Use the encoding scheme used by the GNU C++ compiler, version 3. +.El +.It Fl V | Fl -version +Print a version identifier for +.Nm +and exit. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr nm 1 , +.Xr strip 1 , +.Xr elftc_demangle 3 +.Sh AUTHORS +The +.Nm +utility was written by +.An "Kai Wang" Aq kaiwang27@users.sourceforge.net . diff --git a/contrib/elftoolchain/cxxfilt/cxxfilt.c b/contrib/elftoolchain/cxxfilt/cxxfilt.c new file mode 100644 index 000000000000..d30cfaeffdd7 --- /dev/null +++ b/contrib/elftoolchain/cxxfilt/cxxfilt.c @@ -0,0 +1,224 @@ +/*- + * Copyright (c) 2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $"); + +#define STRBUFSZ 8192 + +static int stripus = 0; +static int noparam = 0; +static int format = 0; + +enum options +{ + OPTION_HELP, + OPTION_VERSION +}; + +static struct option longopts[] = +{ + {"format", required_argument, NULL, 's'}, + {"help", no_argument, NULL, OPTION_HELP}, + {"no-params", no_argument, NULL, 'p'}, + {"no-strip-underscores", no_argument, NULL, 'n'}, + {"strip-underscores", no_argument, NULL, '_'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} +}; + +static struct { + const char *fname; + int fvalue; +} flist[] = { + {"auto", 0}, + {"arm", ELFTC_DEM_ARM}, + {"gnu", ELFTC_DEM_GNU2}, + {"gnu-v3", ELFTC_DEM_GNU3} +}; + +#define USAGE_MESSAGE "\ +Usage: %s [options] [encoded-names...]\n\ + Translate C++ symbol names to human-readable form.\n\n\ + Options:\n\ + -_ | --strip-underscores Remove leading underscores prior to decoding.\n\ + -n | --no-strip-underscores Do not remove leading underscores.\n\ + -p | --no-params (Accepted but ignored).\n\ + -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\ + Valid schemes are: 'arm', 'auto', 'gnu' and\n\ + 'gnu-v3'.\n\ + --help Print a help message.\n\ + --version Print a version identifier and exit.\n" + +static void +usage(void) +{ + + (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(1); +} + +static void +version(void) +{ + fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); + exit(0); +} + +static int +find_format(const char *fstr) +{ + int i; + + for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) { + if (!strcmp(fstr, flist[i].fname)) + return (flist[i].fvalue); + } + + return (-1); +} + +static char * +demangle(char *name, int strict, int *pos) +{ + static char dem[STRBUFSZ]; + char nb[STRBUFSZ]; + int p, t; + + if (stripus && *name == '_') { + strncpy(nb, name + 1, sizeof(nb) - 1); + t = 1; + } else { + strncpy(nb, name, sizeof(nb) - 1); + t = 0; + } + nb[sizeof(nb) - 1] = '\0'; + + p = strlen(nb); + if (p <= 0) + return NULL; + + while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) { + if (!strict && p > 1) { + nb[--p] = '\0'; + continue; + } else + return (NULL); + } + + if (pos != NULL) + *pos = t ? p + 1 : p; + + return (dem); +} + +int +main(int argc, char **argv) +{ + char *dem, buf[STRBUFSZ]; + int c, i, p, s, opt; + + while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != + -1) { + switch (opt) { + case '_': + stripus = 1; + break; + case 'n': + stripus = 0; + break; + case 'p': + noparam = 1; + break; + case 's': + if ((format = find_format(optarg)) < 0) + errx(EXIT_FAILURE, "unsupported format: %s", + optarg); + break; + case 'V': + version(); + /* NOT REACHED */ + case OPTION_HELP: + default: + usage(); + /* NOT REACHED */ + } + } + + argv += optind; + argc -= optind; + + if (*argv != NULL) { + for (i = 0; i < argc; i++) { + if ((dem = demangle(argv[i], 1, NULL)) == NULL) + fprintf(stderr, "Failed: %s\n", argv[i]); + else + printf("%s\n", dem); + } + } else { + p = 0; + for (;;) { + c = fgetc(stdin); + if (c == EOF || !isprint(c) || strchr(" \t\n", c)) { + if (p > 0) { + buf[p] = '\0'; + if ((dem = demangle(buf, 0, &s)) == + NULL) + printf("%s", buf); + else { + printf("%s", dem); + for (i = s; i < p; i++) + putchar(buf[i]); + } + p = 0; + } + if (c == EOF) + break; + if (isprint(c) || strchr(" \t\n", c)) + putchar(c); + } else { + if ((size_t) p >= sizeof(buf) - 1) + warnx("buffer overflowed"); + else + buf[p++] = c; + } + + } + } + + exit(0); +} diff --git a/contrib/elftoolchain/elfcopy/Makefile b/contrib/elftoolchain/elfcopy/Makefile new file mode 100644 index 000000000000..cb1a31b400ee --- /dev/null +++ b/contrib/elftoolchain/elfcopy/Makefile @@ -0,0 +1,41 @@ +# $Id: Makefile 2290 2011-12-04 07:20:46Z jkoshy $ + +TOP= .. + +PROG= elfcopy + +SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c + +WARNS?= 5 + +DPADD= ${LIBELF} ${LIBELFTC} +LDADD= -lelf -lelftc + +.if !defined(LIBELF_AR) +LDADD+= -larchive +.endif + +MAN= elfcopy.1 mcs.1 strip.1 + +NO_SHARED?= yes + +LINKS= ${BINDIR}/elfcopy ${BINDIR}/strip \ + ${BINDIR}/elfcopy ${BINDIR}/mcs + +EXTRA_TARGETS= strip mcs + +CLEANFILES+= ${EXTRA_TARGETS} + +# Create in-place symbolic links to "elfcopy" at build time. + +all: ${EXTRA_TARGETS} + +${EXTRA_TARGETS}: ${PROG} + ln -s ${PROG} ${.TARGET} + +.include "${TOP}/mk/elftoolchain.prog.mk" + +.if ${OS_HOST} == "OpenBSD" +CFLAGS+= -I/usr/local/include +LDFLAGS+= -L/usr/local/lib +.endif diff --git a/contrib/elftoolchain/elfcopy/archive.c b/contrib/elftoolchain/elfcopy/archive.c new file mode 100644 index 000000000000..a4f8017989ba --- /dev/null +++ b/contrib/elftoolchain/elfcopy/archive.c @@ -0,0 +1,528 @@ +/*- + * Copyright (c) 2007-2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#ifndef LIBELF_AR +#include +#include +#endif /* ! LIBELF_AR */ + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: archive.c 2370 2011-12-29 12:48:12Z jkoshy $"); + +#define _ARMAG_LEN 8 /* length of ar magic string */ +#define _ARHDR_LEN 60 /* length of ar header */ +#define _INIT_AS_CAP 128 /* initial archive string table size */ +#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */ +#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */ +#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */ + +#ifndef LIBELF_AR +static void ac_read_objs(struct elfcopy *ecp, int ifd); +static void ac_write_cleanup(struct elfcopy *ecp); +static void ac_write_data(struct archive *a, const void *buf, size_t s); +static void ac_write_objs(struct elfcopy *ecp, int ofd); +#endif /* ! LIBELF_AR */ +static void add_to_ar_str_table(struct elfcopy *elfcopy, const char *name); +static void add_to_ar_sym_table(struct elfcopy *ecp, const char *name); +static void extract_arsym(struct elfcopy *ecp); +static void process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj); +static void sync_ar(struct elfcopy *ecp); + + +static void +process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj) +{ + struct stat sb; + char *tempfile; + int fd; + + /* Output to a temporary file. */ + create_tempfile(&tempfile, &fd); + if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); + create_elf(ecp); + elf_end(ecp->ein); + elf_end(ecp->eout); + free(obj->buf); + obj->buf = NULL; + + /* Extract archive symbols. */ + if (lseek(fd, 0, SEEK_SET) < 0) + err(EXIT_FAILURE, "lseek failed for '%s'", tempfile); + if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + extract_arsym(ecp); + elf_end(ecp->eout); + + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, "fstat %s failed", tempfile); + if (lseek(fd, 0, SEEK_SET) < 0) + err(EXIT_FAILURE, "lseek %s failed", tempfile); + obj->size = sb.st_size; + if ((obj->maddr = malloc(obj->size)) == NULL) + err(EXIT_FAILURE, "memory allocation failed for '%s'", + tempfile); + if ((size_t) read(fd, obj->maddr, obj->size) != obj->size) + err(EXIT_FAILURE, "read failed for '%s'", tempfile); + if (unlink(tempfile)) + err(EXIT_FAILURE, "unlink %s failed", tempfile); + free(tempfile); + close(fd); + if (strlen(obj->name) > _MAXNAMELEN_SVR4) + add_to_ar_str_table(ecp, obj->name); + ecp->rela_off += _ARHDR_LEN + obj->size + obj->size % 2; + STAILQ_INSERT_TAIL(&ecp->v_arobj, obj, objs); +} + +/* + * Append to the archive string table buffer. + */ +static void +add_to_ar_str_table(struct elfcopy *ecp, const char *name) +{ + + if (ecp->as == NULL) { + ecp->as_cap = _INIT_AS_CAP; + ecp->as_sz = 0; + if ((ecp->as = malloc(ecp->as_cap)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + } + + /* + * The space required for holding one member name in as table includes: + * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding). + */ + while (ecp->as_sz + strlen(name) + 3 > ecp->as_cap) { + ecp->as_cap *= 2; + ecp->as = realloc(ecp->as, ecp->as_cap); + if (ecp->as == NULL) + err(EXIT_FAILURE, "realloc failed"); + } + strncpy(&ecp->as[ecp->as_sz], name, strlen(name)); + ecp->as_sz += strlen(name); + ecp->as[ecp->as_sz++] = '/'; + ecp->as[ecp->as_sz++] = '\n'; +} + +/* + * Append to the archive symbol table buffer. + */ +static void +add_to_ar_sym_table(struct elfcopy *ecp, const char *name) +{ + + if (ecp->s_so == NULL) { + if ((ecp->s_so = malloc(_INIT_SYMOFF_CAP)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + ecp->s_so_cap = _INIT_SYMOFF_CAP; + ecp->s_cnt = 0; + } + + if (ecp->s_sn == NULL) { + if ((ecp->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + ecp->s_sn_cap = _INIT_SYMNAME_CAP; + ecp->s_sn_sz = 0; + } + + if (ecp->s_cnt * sizeof(uint32_t) >= ecp->s_so_cap) { + ecp->s_so_cap *= 2; + ecp->s_so = realloc(ecp->s_so, ecp->s_so_cap); + if (ecp->s_so == NULL) + err(EXIT_FAILURE, "realloc failed"); + } + ecp->s_so[ecp->s_cnt] = ecp->rela_off; + ecp->s_cnt++; + + /* + * The space required for holding one symbol name in sn table includes: + * strlen(name) + (1 for '\n') + (possibly 1 for padding). + */ + while (ecp->s_sn_sz + strlen(name) + 2 > ecp->s_sn_cap) { + ecp->s_sn_cap *= 2; + ecp->s_sn = realloc(ecp->s_sn, ecp->s_sn_cap); + if (ecp->s_sn == NULL) + err(EXIT_FAILURE, "realloc failed"); + } + strncpy(&ecp->s_sn[ecp->s_sn_sz], name, strlen(name)); + ecp->s_sn_sz += strlen(name); + ecp->s_sn[ecp->s_sn_sz++] = '\0'; +} + +static void +sync_ar(struct elfcopy *ecp) +{ + size_t s_sz; /* size of archive symbol table. */ + size_t pm_sz; /* size of pseudo members */ + int i; + + /* + * Pad the symbol name string table. It is treated specially because + * symbol name table should be padded by a '\0', not the common '\n' + * for other members. The size of sn table includes the pad bit. + */ + if (ecp->s_cnt != 0 && ecp->s_sn_sz % 2 != 0) + ecp->s_sn[ecp->s_sn_sz++] = '\0'; + + /* + * Archive string table is padded by a "\n" as the normal members. + * The difference is that the size of archive string table counts + * in the pad bit, while normal members' size fileds do not. + */ + if (ecp->as != NULL && ecp->as_sz % 2 != 0) + ecp->as[ecp->as_sz++] = '\n'; + + /* + * If there is a symbol table, calculate the size of pseudo members, + * convert previously stored relative offsets to absolute ones, and + * then make them Big Endian. + * + * absolute_offset = htobe32(relative_offset + size_of_pseudo_members) + */ + + if (ecp->s_cnt != 0) { + s_sz = (ecp->s_cnt + 1) * sizeof(uint32_t) + ecp->s_sn_sz; + pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz); + if (ecp->as != NULL) + pm_sz += _ARHDR_LEN + ecp->as_sz; + for (i = 0; (size_t)i < ecp->s_cnt; i++) + *(ecp->s_so + i) = htobe32(*(ecp->s_so + i) + + pm_sz); + } +} + +/* + * Extract global symbols from archive members. + */ +static void +extract_arsym(struct elfcopy *ecp) +{ + Elf_Scn *scn; + GElf_Shdr shdr; + GElf_Sym sym; + Elf_Data *data; + char *name; + size_t n, shstrndx; + int elferr, tabndx, len, i; + + if (elf_kind(ecp->eout) != ELF_K_ELF) { + warnx("internal: cannot extract symbols from non-elf object"); + return; + } + if (elf_getshstrndx(ecp->eout, &shstrndx) == 0) { + warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); + return; + } + + tabndx = -1; + scn = NULL; + while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != &shdr) { + warnx("elf_getshdr failed: %s", elf_errmsg(-1)); + continue; + } + if ((name = elf_strptr(ecp->eout, shstrndx, shdr.sh_name)) == + NULL) { + warnx("elf_strptr failed: %s", elf_errmsg(-1)); + continue; + } + if (strcmp(name, ".strtab") == 0) { + tabndx = elf_ndxscn(scn); + break; + } + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + /* Ignore members without symbol table. */ + if (tabndx == -1) + return; + + scn = NULL; + while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != &shdr) { + warnx("elf_getshdr failed: %s", elf_errmsg(-1)); + continue; + } + if (shdr.sh_type != SHT_SYMTAB) + continue; + + data = NULL; + n = 0; + while (n < shdr.sh_size && + (data = elf_getdata(scn, data)) != NULL) { + len = data->d_size / shdr.sh_entsize; + for (i = 0; i < len; i++) { + if (gelf_getsym(data, i, &sym) != &sym) { + warnx("gelf_getsym failed: %s", + elf_errmsg(-1)); + continue; + } + + /* keep only global or weak symbols */ + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL && + GELF_ST_BIND(sym.st_info) != STB_WEAK) + continue; + + /* keep only defined symbols */ + if (sym.st_shndx == SHN_UNDEF) + continue; + + if ((name = elf_strptr(ecp->eout, tabndx, + sym.st_name)) == NULL) { + warnx("elf_strptr failed: %s", + elf_errmsg(-1)); + continue; + } + + add_to_ar_sym_table(ecp, name); + } + } + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); +} + +#ifndef LIBELF_AR + +/* + * Convenient wrapper for general libarchive error handling. + */ +#define AC(CALL) do { \ + if ((CALL)) \ + errx(EXIT_FAILURE, "%s", archive_error_string(a)); \ +} while (0) + +/* Earlier versions of libarchive had some functions that returned 'void'. */ +#if ARCHIVE_VERSION_NUMBER >= 2000000 +#define ACV(CALL) AC(CALL) +#else +#define ACV(CALL) do { \ + (CALL); \ + } while (0) +#endif + +int +ac_detect_ar(int ifd) +{ + struct archive *a; + struct archive_entry *entry; + int r; + + r = -1; + if ((a = archive_read_new()) == NULL) + return (0); + archive_read_support_compression_none(a); + archive_read_support_format_ar(a); + if (archive_read_open_fd(a, ifd, 10240) == ARCHIVE_OK) + r = archive_read_next_header(a, &entry); + archive_read_close(a); + archive_read_finish(a); + + return (r == ARCHIVE_OK); +} + +void +ac_create_ar(struct elfcopy *ecp, int ifd, int ofd) +{ + + ac_read_objs(ecp, ifd); + sync_ar(ecp); + ac_write_objs(ecp, ofd); + ac_write_cleanup(ecp); +} + +static void +ac_read_objs(struct elfcopy *ecp, int ifd) +{ + struct archive *a; + struct archive_entry *entry; + struct ar_obj *obj; + const char *name; + char *buff; + size_t size; + int r; + + ecp->rela_off = 0; + if (lseek(ifd, 0, SEEK_SET) == -1) + err(EXIT_FAILURE, "lseek failed"); + if ((a = archive_read_new()) == NULL) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); + archive_read_support_compression_none(a); + archive_read_support_format_ar(a); + AC(archive_read_open_fd(a, ifd, 10240)); + for(;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_FATAL) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); + if (r == ARCHIVE_EOF) + break; + if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) + warnx("%s", archive_error_string(a)); + if (r == ARCHIVE_RETRY) + continue; + + name = archive_entry_pathname(entry); + + /* skip pseudo members. */ + if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0) + continue; + + size = archive_entry_size(entry); + + if (size > 0) { + if ((buff = malloc(size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if (archive_read_data(a, buff, size) != (ssize_t)size) { + warnx("%s", archive_error_string(a)); + free(buff); + continue; + } + if ((obj = malloc(sizeof(*obj))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if ((obj->name = strdup(name)) == NULL) + err(EXIT_FAILURE, "strdup failed"); + obj->buf = buff; + obj->uid = archive_entry_uid(entry); + obj->gid = archive_entry_gid(entry); + obj->md = archive_entry_mode(entry); + obj->mtime = archive_entry_mtime(entry); + if ((ecp->ein = elf_memory(buff, size)) == NULL) + errx(EXIT_FAILURE, "elf_memory() failed: %s", + elf_errmsg(-1)); + if (elf_kind(ecp->ein) != ELF_K_ELF) + errx(EXIT_FAILURE, + "file format not recognized"); + process_ar_obj(ecp, obj); + } + } + AC(archive_read_close(a)); + ACV(archive_read_finish(a)); +} + +static void +ac_write_objs(struct elfcopy *ecp, int ofd) +{ + struct archive *a; + struct archive_entry *entry; + struct ar_obj *obj; + int nr; + + if ((a = archive_write_new()) == NULL) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); + archive_write_set_format_ar_svr4(a); + archive_write_set_compression_none(a); + AC(archive_write_open_fd(a, ofd)); + + /* Write the archive symbol table, even if it's empty. */ + entry = archive_entry_new(); + archive_entry_copy_pathname(entry, "/"); + archive_entry_set_mtime(entry, time(NULL), 0); + archive_entry_set_size(entry, (ecp->s_cnt + 1) * sizeof(uint32_t) + + ecp->s_sn_sz); + AC(archive_write_header(a, entry)); + nr = htobe32(ecp->s_cnt); + ac_write_data(a, &nr, sizeof(uint32_t)); + ac_write_data(a, ecp->s_so, sizeof(uint32_t) * ecp->s_cnt); + ac_write_data(a, ecp->s_sn, ecp->s_sn_sz); + archive_entry_free(entry); + + /* Write the archive string table, if exist. */ + if (ecp->as != NULL) { + entry = archive_entry_new(); + archive_entry_copy_pathname(entry, "//"); + archive_entry_set_size(entry, ecp->as_sz); + AC(archive_write_header(a, entry)); + ac_write_data(a, ecp->as, ecp->as_sz); + archive_entry_free(entry); + } + + /* Write normal members. */ + STAILQ_FOREACH(obj, &ecp->v_arobj, objs) { + entry = archive_entry_new(); + archive_entry_copy_pathname(entry, obj->name); + archive_entry_set_uid(entry, obj->uid); + archive_entry_set_gid(entry, obj->gid); + archive_entry_set_mode(entry, obj->md); + archive_entry_set_size(entry, obj->size); + archive_entry_set_mtime(entry, obj->mtime, 0); + archive_entry_set_filetype(entry, AE_IFREG); + AC(archive_write_header(a, entry)); + ac_write_data(a, obj->maddr, obj->size); + archive_entry_free(entry); + } + + AC(archive_write_close(a)); + ACV(archive_write_finish(a)); +} + +static void +ac_write_cleanup(struct elfcopy *ecp) +{ + struct ar_obj *obj, *obj_temp; + + STAILQ_FOREACH_SAFE(obj, &ecp->v_arobj, objs, obj_temp) { + STAILQ_REMOVE(&ecp->v_arobj, obj, ar_obj, objs); + if (obj->maddr != NULL) + free(obj->maddr); + free(obj->name); + free(obj); + } + + free(ecp->as); + free(ecp->s_so); + free(ecp->s_sn); + ecp->as = NULL; + ecp->s_so = NULL; + ecp->s_sn = NULL; +} + +/* + * Wrapper for archive_write_data(). + */ +static void +ac_write_data(struct archive *a, const void *buf, size_t s) +{ + if (archive_write_data(a, buf, s) != (ssize_t)s) + errx(EXIT_FAILURE, "%s", archive_error_string(a)); +} + +#endif /* ! LIBELF_AR */ diff --git a/contrib/elftoolchain/elfcopy/ascii.c b/contrib/elftoolchain/elfcopy/ascii.c new file mode 100644 index 000000000000..968e5c667f63 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/ascii.c @@ -0,0 +1,1078 @@ +/*- + * Copyright (c) 2010,2011 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: ascii.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); + +static void append_data(struct section *s, const void *buf, size_t sz); +static char hex_digit(uint8_t n); +static int hex_value(int x); +static void finalize_data_section(struct section *s); +static int ishexdigit(int x); +static int ihex_read(const char *line, char *type, uint64_t *addr, + uint64_t *num, uint8_t *data, size_t *sz); +static void ihex_write(int ofd, int type, uint64_t addr, uint64_t num, + const void *buf, size_t sz); +static void ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz); +static void ihex_write_01(int ofd); +static void ihex_write_04(int ofd, uint16_t addr); +static void ihex_write_05(int ofd, uint64_t e_entry); +static struct section *new_data_section(struct elfcopy *ecp, int sec_index, + uint64_t off, uint64_t addr); +static int read_num(const char *line, int *len, uint64_t *num, size_t sz, + int *checksum); +static int srec_read(const char *line, char *type, uint64_t *addr, + uint8_t *data, size_t *sz); +static void srec_write(int ofd, char type, uint64_t addr, const void *buf, + size_t sz); +static void srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn, + GElf_Shdr *sh); +static void srec_write_S0(int ofd, const char *ofn); +static void srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf, + size_t sz, size_t rlen); +static void srec_write_Se(int ofd, uint64_t e_entry, int forceS3); +static void write_num(char *line, int *len, uint64_t num, size_t sz, + int *checksum); + +#define _LINE_BUFSZ 1024 +#define _DATA_BUFSZ 256 + +/* + * Convert ELF object to S-Record. + */ +void +create_srec(struct elfcopy *ecp, int ifd, int ofd, const char *ofn) +{ + Elf *e; + Elf_Scn *scn; + Elf_Data *d; + GElf_Ehdr eh; + GElf_Shdr sh; + uint64_t max_addr; + size_t rlen; + int elferr, addr_sz; + char dr; + + if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + /* Output a symbol table for `symbolsrec' target. */ + if (!strncmp(ecp->otgt, "symbolsrec", strlen("symbolsrec"))) { + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", + elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if (sh.sh_type != SHT_SYMTAB) + continue; + srec_write_symtab(ofd, ofn, e, scn, &sh); + break; + } + } + + if (ecp->flags & SREC_FORCE_S3) + dr = '3'; + else { + /* + * Find maximum address size in the first iteration. + */ + max_addr = 0; + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", + elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((sh.sh_flags & SHF_ALLOC) == 0 || + sh.sh_type == SHT_NOBITS || + sh.sh_size == 0) + continue; + if ((uint64_t) sh.sh_addr > max_addr) + max_addr = sh.sh_addr; + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + if (max_addr <= 0xFFFF) + dr = '1'; + else if (max_addr <= 0xFFFFFF) + dr = '2'; + else + dr = '3'; + } + + if (ecp->flags & SREC_FORCE_LEN) { + addr_sz = dr - '0' + 1; + if (ecp->srec_len < 1) + rlen = 1; + else if (ecp->srec_len + addr_sz + 1 > 255) + rlen = 255 - (addr_sz + 1); + else + rlen = ecp->srec_len; + } else + rlen = 16; + + /* Generate S0 record which contains the output filename. */ + srec_write_S0(ofd, ofn); + + /* Generate S{1,2,3} data records for section data. */ + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((sh.sh_flags & SHF_ALLOC) == 0 || + sh.sh_type == SHT_NOBITS || + sh.sh_size == 0) + continue; + if (sh.sh_addr > 0xFFFFFFFF) { + warnx("address space too big for S-Record file"); + continue; + } + (void) elf_errno(); + if ((d = elf_getdata(scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + continue; + } + if (d->d_buf == NULL || d->d_size == 0) + continue; + srec_write_Sd(ofd, dr, sh.sh_addr, d->d_buf, d->d_size, rlen); + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + /* Generate S{7,8,9} end of block recrod. */ + if (gelf_getehdr(e, &eh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + srec_write_Se(ofd, eh.e_entry, ecp->flags & SREC_FORCE_S3); +} + +void +create_elf_from_srec(struct elfcopy *ecp, int ifd) +{ + char line[_LINE_BUFSZ], name[_LINE_BUFSZ]; + uint8_t data[_DATA_BUFSZ]; + GElf_Ehdr oeh; + struct section *s, *shtab; + FILE *ifp; + uint64_t addr, entry, off, sec_addr; + uintmax_t st_value; + size_t sz; + int _ifd, first, sec_index, in_symtab, symtab_created; + char *rlt; + char type; + + if ((_ifd = dup(ifd)) < 0) + err(EXIT_FAILURE, "dup failed"); + if ((ifp = fdopen(_ifd, "r")) == NULL) + err(EXIT_FAILURE, "fdopen failed"); + + /* Create EHDR for output .o file. */ + if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) + errx(EXIT_FAILURE, "gelf_newehdr failed: %s", + elf_errmsg(-1)); + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Initialise e_ident fields. */ + oeh.e_ident[EI_CLASS] = ecp->oec; + oeh.e_ident[EI_DATA] = ecp->oed; + /* + * TODO: Set OSABI according to the OS platform where elfcopy(1) + * was build. (probably) + */ + oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; + oeh.e_machine = ecp->oem; + oeh.e_type = ET_REL; + oeh.e_entry = 0; + + ecp->flags |= RELOCATABLE; + + /* Create .shstrtab section */ + init_shstrtab(ecp); + ecp->shstrtab->off = 0; + + /* Data sections are inserted after EHDR. */ + off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); + if (off == 0) + errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); + + /* Create data sections. */ + s = NULL; + first = 1; + sec_index = 1; + sec_addr = entry = 0; + while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { + if (line[0] == '\r' || line[0] == '\n') + continue; + if (line[0] == '$' && line[1] == '$') { + ecp->flags |= SYMTAB_EXIST; + while ((rlt = fgets(line, _LINE_BUFSZ, ifp)) != NULL) { + if (line[0] == '$' && line[1] == '$') + break; + } + if (rlt == NULL) + break; + continue; + } + if (line[0] != 'S' || line[1] < '0' || line[1] > '9') { + warnx("Invalid srec record"); + continue; + } + if (srec_read(line, &type, &addr, data, &sz) < 0) { + warnx("Invalid srec record or mismatched checksum"); + continue; + } + switch (type) { + case '1': + case '2': + case '3': + if (sz == 0) + break; + if (first || sec_addr != addr) { + if (s != NULL) + finalize_data_section(s); + s = new_data_section(ecp, sec_index, off, + addr); + if (s == NULL) { + warnx("new_data_section failed"); + break; + } + sec_index++; + sec_addr = addr; + first = 0; + } + append_data(s, data, sz); + off += sz; + sec_addr += sz; + break; + case '7': + case '8': + case '9': + entry = addr; + break; + default: + break; + } + } + if (s != NULL) + finalize_data_section(s); + if (ferror(ifp)) + warn("fgets failed"); + + /* Insert .shstrtab after data sections. */ + if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + insert_to_sec_list(ecp, ecp->shstrtab, 1); + + /* Insert section header table here. */ + shtab = insert_shtab(ecp, 1); + + /* + * Rescan and create symbol table if we found '$$' section in + * the first scan. + */ + symtab_created = 0; + in_symtab = 0; + if (ecp->flags & SYMTAB_EXIST) { + if (fseek(ifp, 0, SEEK_SET) < 0) { + warn("fseek failed"); + ecp->flags &= ~SYMTAB_EXIST; + goto done; + } + while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { + if (in_symtab) { + if (line[0] == '$' && line[1] == '$') { + in_symtab = 0; + continue; + } + if (sscanf(line, "%s $%jx", name, + &st_value) != 2) { + warnx("Invalid symbolsrec record"); + continue; + } + if (!symtab_created) { + create_external_symtab(ecp); + symtab_created = 1; + } + add_to_symtab(ecp, name, st_value, 0, SHN_ABS, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); + } + if (line[0] == '$' && line[1] == '$') { + in_symtab = 1; + continue; + } + } + } + if (ferror(ifp)) + warn("fgets failed"); + if (symtab_created) { + finalize_external_symtab(ecp); + create_symtab_data(ecp); + /* Count in .symtab and .strtab section headers. */ + shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT); + } else + ecp->flags &= ~SYMTAB_EXIST; + +done: + fclose(ifp); + + /* Set entry point. */ + oeh.e_entry = entry; + + /* + * Write the underlying ehdr. Note that it should be called + * before elf_setshstrndx() since it will overwrite e->e_shstrndx. + */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Generate section name string table (.shstrtab). */ + set_shstrtab(ecp); + + /* Update sh_name pointer for each section header entry. */ + update_shdr(ecp, 0); + + /* Renew oeh to get the updated e_shstrndx. */ + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Resync section offsets. */ + resync_sections(ecp); + + /* Store SHDR offset in EHDR. */ + oeh.e_shoff = shtab->off; + + /* Update ehdr since we modified e_shoff. */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Write out the output elf object. */ + if (elf_update(ecp->eout, ELF_C_WRITE) < 0) + errx(EXIT_FAILURE, "elf_update() failed: %s", + elf_errmsg(-1)); + + /* Release allocated resource. */ + free_elf(ecp); +} + +void +create_ihex(int ifd, int ofd) +{ + Elf *e; + Elf_Scn *scn; + Elf_Data *d; + GElf_Ehdr eh; + GElf_Shdr sh; + int elferr; + uint16_t addr_hi, old_addr_hi; + + if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + old_addr_hi = 0; + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((sh.sh_flags & SHF_ALLOC) == 0 || + sh.sh_type == SHT_NOBITS || + sh.sh_size == 0) + continue; + if (sh.sh_addr > 0xFFFFFFFF) { + warnx("address space too big for Intel Hex file"); + continue; + } + (void) elf_errno(); + if ((d = elf_getdata(scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + continue; + } + if (d->d_buf == NULL || d->d_size == 0) + continue; + addr_hi = (sh.sh_addr >> 16) & 0xFFFF; + if (addr_hi > 0 && addr_hi != old_addr_hi) { + /* Write 04 record if addr_hi is new. */ + old_addr_hi = addr_hi; + ihex_write_04(ofd, addr_hi); + } + ihex_write_00(ofd, sh.sh_addr, d->d_buf, d->d_size); + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + if (gelf_getehdr(e, &eh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + ihex_write_05(ofd, eh.e_entry); + ihex_write_01(ofd); +} + +void +create_elf_from_ihex(struct elfcopy *ecp, int ifd) +{ + char line[_LINE_BUFSZ]; + uint8_t data[_DATA_BUFSZ]; + GElf_Ehdr oeh; + struct section *s, *shtab; + FILE *ifp; + uint64_t addr, addr_base, entry, num, off, rec_addr, sec_addr; + size_t sz; + int _ifd, first, sec_index; + char type; + + if ((_ifd = dup(ifd)) < 0) + err(EXIT_FAILURE, "dup failed"); + if ((ifp = fdopen(_ifd, "r")) == NULL) + err(EXIT_FAILURE, "fdopen failed"); + + /* Create EHDR for output .o file. */ + if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) + errx(EXIT_FAILURE, "gelf_newehdr failed: %s", + elf_errmsg(-1)); + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Initialise e_ident fields. */ + oeh.e_ident[EI_CLASS] = ecp->oec; + oeh.e_ident[EI_DATA] = ecp->oed; + /* + * TODO: Set OSABI according to the OS platform where elfcopy(1) + * was build. (probably) + */ + oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; + oeh.e_machine = ecp->oem; + oeh.e_type = ET_REL; + oeh.e_entry = 0; + + ecp->flags |= RELOCATABLE; + + /* Create .shstrtab section */ + init_shstrtab(ecp); + ecp->shstrtab->off = 0; + + /* Data sections are inserted after EHDR. */ + off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); + if (off == 0) + errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); + + /* Create data sections. */ + s = NULL; + first = 1; + sec_index = 1; + addr_base = rec_addr = sec_addr = entry = 0; + while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { + if (line[0] == '\r' || line[0] == '\n') + continue; + if (line[0] != ':') { + warnx("Invalid ihex record"); + continue; + } + if (ihex_read(line, &type, &addr, &num, data, &sz) < 0) { + warnx("Invalid ihex record or mismatched checksum"); + continue; + } + switch (type) { + case '0': + /* Data record. */ + if (sz == 0) + break; + rec_addr = addr_base + addr; + if (first || sec_addr != rec_addr) { + if (s != NULL) + finalize_data_section(s); + s = new_data_section(ecp, sec_index, off, + rec_addr); + if (s == NULL) { + warnx("new_data_section failed"); + break; + } + sec_index++; + sec_addr = rec_addr; + first = 0; + } + append_data(s, data, sz); + off += sz; + sec_addr += sz; + break; + case '1': + /* End of file record. */ + goto done; + case '2': + /* Extended segment address record. */ + addr_base = addr << 4; + break; + case '3': + /* Start segment address record (CS:IP). Ignored. */ + break; + case '4': + /* Extended linear address record. */ + addr_base = num << 16; + break; + case '5': + /* Start linear address record. */ + entry = num; + break; + default: + break; + } + } +done: + if (s != NULL) + finalize_data_section(s); + if (ferror(ifp)) + warn("fgets failed"); + fclose(ifp); + + /* Insert .shstrtab after data sections. */ + if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + insert_to_sec_list(ecp, ecp->shstrtab, 1); + + /* Insert section header table here. */ + shtab = insert_shtab(ecp, 1); + + /* Set entry point. */ + oeh.e_entry = entry; + + /* + * Write the underlying ehdr. Note that it should be called + * before elf_setshstrndx() since it will overwrite e->e_shstrndx. + */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Generate section name string table (.shstrtab). */ + set_shstrtab(ecp); + + /* Update sh_name pointer for each section header entry. */ + update_shdr(ecp, 0); + + /* Renew oeh to get the updated e_shstrndx. */ + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Resync section offsets. */ + resync_sections(ecp); + + /* Store SHDR offset in EHDR. */ + oeh.e_shoff = shtab->off; + + /* Update ehdr since we modified e_shoff. */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Write out the output elf object. */ + if (elf_update(ecp->eout, ELF_C_WRITE) < 0) + errx(EXIT_FAILURE, "elf_update() failed: %s", + elf_errmsg(-1)); + + /* Release allocated resource. */ + free_elf(ecp); +} + +#define _SEC_NAMESZ 64 +#define _SEC_INIT_CAP 1024 + +static struct section * +new_data_section(struct elfcopy *ecp, int sec_index, uint64_t off, + uint64_t addr) +{ + char *name; + + if ((name = malloc(_SEC_NAMESZ)) == NULL) + errx(EXIT_FAILURE, "malloc failed"); + snprintf(name, _SEC_NAMESZ, ".sec%d", sec_index); + + return (create_external_section(ecp, name, name, NULL, 0, off, + SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, addr, 0)); +} + +static void +finalize_data_section(struct section *s) +{ + Elf_Data *od; + + if ((od = elf_newdata(s->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s", + elf_errmsg(-1)); + od->d_align = s->align; + od->d_off = 0; + od->d_buf = s->buf; + od->d_size = s->sz; + od->d_version = EV_CURRENT; +} + +static void +append_data(struct section *s, const void *buf, size_t sz) +{ + uint8_t *p; + + if (s->buf == NULL) { + s->sz = 0; + s->cap = _SEC_INIT_CAP; + if ((s->buf = malloc(s->cap)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + } + + while (sz + s->sz > s->cap) { + s->cap *= 2; + if ((s->buf = realloc(s->buf, s->cap)) == NULL) + err(EXIT_FAILURE, "realloc failed"); + } + + p = s->buf; + memcpy(&p[s->sz], buf, sz); + s->sz += sz; +} + +static int +srec_read(const char *line, char *type, uint64_t *addr, uint8_t *data, + size_t *sz) +{ + uint64_t count, _checksum, num; + size_t addr_sz; + int checksum, i, len; + + checksum = 0; + len = 2; + if (read_num(line, &len, &count, 1, &checksum) < 0) + return (-1); + *type = line[1]; + switch (*type) { + case '0': + case '1': + case '5': + case '9': + addr_sz = 2; + break; + case '2': + case '8': + addr_sz = 3; + break; + case '3': + case '7': + addr_sz = 4; + break; + default: + return (-1); + } + + if (read_num(line, &len, addr, addr_sz, &checksum) < 0) + return (-1); + + count -= addr_sz + 1; + if (*type >= '0' && *type <= '3') { + for (i = 0; (uint64_t) i < count; i++) { + if (read_num(line, &len, &num, 1, &checksum) < 0) + return -1; + data[i] = (uint8_t) num; + } + *sz = count; + } else + *sz = 0; + + if (read_num(line, &len, &_checksum, 1, NULL) < 0) + return (-1); + + if ((int) _checksum != (~checksum & 0xFF)) + return (-1); + + return (0); +} + +static void +srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn, GElf_Shdr *sh) +{ + char line[_LINE_BUFSZ]; + GElf_Sym sym; + Elf_Data *d; + const char *name; + size_t sc; + int elferr, i; + +#define _WRITE_LINE do { \ + if (write(ofd, line, strlen(line)) != (ssize_t) strlen(line)) \ + errx(EXIT_FAILURE, "write failed"); \ + } while (0) + + + (void) elf_errno(); + if ((d = elf_getdata(scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(-1)); + return; + } + if (d->d_buf == NULL || d->d_size == 0) + return; + + snprintf(line, sizeof(line), "$$ %s\r\n", ofn); + _WRITE_LINE; + sc = d->d_size / sh->sh_entsize; + for (i = 1; (size_t) i < sc; i++) { + if (gelf_getsym(d, i, &sym) != &sym) { + warnx("gelf_getsym failed: %s", elf_errmsg(-1)); + continue; + } + if (GELF_ST_TYPE(sym.st_info) == STT_SECTION || + GELF_ST_TYPE(sym.st_info) == STT_FILE) + continue; + if ((name = elf_strptr(e, sh->sh_link, sym.st_name)) == NULL) { + warnx("elf_strptr failed: %s", elf_errmsg(-1)); + continue; + } + snprintf(line, sizeof(line), " %s $%jx\r\n", name, + (uintmax_t) sym.st_value); + _WRITE_LINE; + } + snprintf(line, sizeof(line), "$$ \r\n"); + _WRITE_LINE; + +#undef _WRITE_LINE +} + +static void +srec_write_S0(int ofd, const char *ofn) +{ + + srec_write(ofd, '0', 0, ofn, strlen(ofn)); +} + +static void +srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf, size_t sz, + size_t rlen) +{ + const uint8_t *p, *pe; + + p = buf; + pe = p + sz; + while (pe - p >= (int) rlen) { + srec_write(ofd, dr, addr, p, rlen); + addr += rlen; + p += rlen; + } + if (pe - p > 0) + srec_write(ofd, dr, addr, p, pe - p); +} + +static void +srec_write_Se(int ofd, uint64_t e_entry, int forceS3) +{ + char er; + + if (e_entry > 0xFFFFFFFF) { + warnx("address space too big for S-Record file"); + return; + } + + if (forceS3) + er = '7'; + else { + if (e_entry <= 0xFFFF) + er = '9'; + else if (e_entry <= 0xFFFFFF) + er = '8'; + else + er = '7'; + } + + srec_write(ofd, er, e_entry, NULL, 0); +} + +static void +srec_write(int ofd, char type, uint64_t addr, const void *buf, size_t sz) +{ + char line[_LINE_BUFSZ]; + const uint8_t *p, *pe; + int len, addr_sz, checksum; + + if (type == '0' || type == '1' || type == '5' || type == '9') + addr_sz = 2; + else if (type == '2' || type == '8') + addr_sz = 3; + else + addr_sz = 4; + + checksum = 0; + line[0] = 'S'; + line[1] = type; + len = 2; + write_num(line, &len, addr_sz + sz + 1, 1, &checksum); + write_num(line, &len, addr, addr_sz, &checksum); + for (p = buf, pe = p + sz; p < pe; p++) + write_num(line, &len, *p, 1, &checksum); + write_num(line, &len, ~checksum & 0xFF, 1, NULL); + line[len++] = '\r'; + line[len++] = '\n'; + if (write(ofd, line, len) != (ssize_t) len) + err(EXIT_FAILURE, "write failed"); +} + +static void +ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz) +{ + uint16_t addr_hi, old_addr_hi; + const uint8_t *p, *pe; + + old_addr_hi = (addr >> 16) & 0xFFFF; + p = buf; + pe = p + sz; + while (pe - p >= 16) { + ihex_write(ofd, 0, addr, 0, p, 16); + addr += 16; + p += 16; + addr_hi = (addr >> 16) & 0xFFFF; + if (addr_hi != old_addr_hi) { + old_addr_hi = addr_hi; + ihex_write_04(ofd, addr_hi); + } + } + if (pe - p > 0) + ihex_write(ofd, 0, addr, 0, p, pe - p); +} + +static int +ihex_read(const char *line, char *type, uint64_t *addr, uint64_t *num, + uint8_t *data, size_t *sz) +{ + uint64_t count, _checksum; + int checksum, i, len; + + *sz = 0; + checksum = 0; + len = 1; + if (read_num(line, &len, &count, 1, &checksum) < 0) + return (-1); + if (read_num(line, &len, addr, 2, &checksum) < 0) + return (-1); + if (line[len++] != '0') + return (-1); + *type = line[len++]; + checksum += *type - '0'; + switch (*type) { + case '0': + for (i = 0; (uint64_t) i < count; i++) { + if (read_num(line, &len, num, 1, &checksum) < 0) + return (-1); + data[i] = (uint8_t) *num; + } + *sz = count; + break; + case '1': + if (count != 0) + return (-1); + break; + case '2': + case '4': + if (count != 2) + return (-1); + if (read_num(line, &len, num, 2, &checksum) < 0) + return (-1); + break; + case '3': + case '5': + if (count != 4) + return (-1); + if (read_num(line, &len, num, 4, &checksum) < 0) + return (-1); + break; + default: + return (-1); + } + + if (read_num(line, &len, &_checksum, 1, &checksum) < 0) + return (-1); + + if ((checksum & 0xFF) != 0) { + return (-1); + } + + return (0); +} + +static void +ihex_write_01(int ofd) +{ + + ihex_write(ofd, 1, 0, 0, NULL, 0); +} + +static void +ihex_write_04(int ofd, uint16_t addr) +{ + + ihex_write(ofd, 4, 0, addr, NULL, 2); +} + +static void +ihex_write_05(int ofd, uint64_t e_entry) +{ + + if (e_entry > 0xFFFFFFFF) { + warnx("address space too big for Intel Hex file"); + return; + } + + ihex_write(ofd, 5, 0, e_entry, NULL, 4); +} + +static void +ihex_write(int ofd, int type, uint64_t addr, uint64_t num, const void *buf, + size_t sz) +{ + char line[_LINE_BUFSZ]; + const uint8_t *p, *pe; + int len, checksum; + + if (sz > 16) + errx(EXIT_FAILURE, "Internal: ihex_write() sz too big"); + checksum = 0; + line[0] = ':'; + len = 1; + write_num(line, &len, sz, 1, &checksum); + write_num(line, &len, addr, 2, &checksum); + write_num(line, &len, type, 1, &checksum); + if (sz > 0) { + if (buf != NULL) { + for (p = buf, pe = p + sz; p < pe; p++) + write_num(line, &len, *p, 1, &checksum); + } else + write_num(line, &len, num, sz, &checksum); + } + write_num(line, &len, (~checksum + 1) & 0xFF, 1, NULL); + line[len++] = '\r'; + line[len++] = '\n'; + if (write(ofd, line, len) != (ssize_t) len) + err(EXIT_FAILURE, "write failed"); +} + +static int +read_num(const char *line, int *len, uint64_t *num, size_t sz, int *checksum) +{ + uint8_t b; + + *num = 0; + for (; sz > 0; sz--) { + if (!ishexdigit(line[*len]) || !ishexdigit(line[*len + 1])) + return (-1); + b = (hex_value(line[*len]) << 4) | hex_value(line[*len + 1]); + *num = (*num << 8) | b; + *len += 2; + if (checksum != NULL) + *checksum = (*checksum + b) & 0xFF; + } + + return (0); +} + +static void +write_num(char *line, int *len, uint64_t num, size_t sz, int *checksum) +{ + uint8_t b; + + for (; sz > 0; sz--) { + b = (num >> ((sz - 1) * 8)) & 0xFF; + line[*len] = hex_digit((b >> 4) & 0xF); + line[*len + 1] = hex_digit(b & 0xF); + *len += 2; + if (checksum != NULL) + *checksum = (*checksum + b) & 0xFF; + } +} + +static char +hex_digit(uint8_t n) +{ + + return ((n < 10) ? '0' + n : 'A' + (n - 10)); +} + +static int +hex_value(int x) +{ + + if (isdigit(x)) + return (x - '0'); + else if (x >= 'a' && x <= 'f') + return (x - 'a' + 10); + else + return (x - 'A' + 10); +} + +static int +ishexdigit(int x) +{ + + if (isdigit(x)) + return (1); + if ((x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) + return (1); + + return (0); +} diff --git a/contrib/elftoolchain/elfcopy/binary.c b/contrib/elftoolchain/elfcopy/binary.c new file mode 100644 index 000000000000..65b49fbe874f --- /dev/null +++ b/contrib/elftoolchain/elfcopy/binary.c @@ -0,0 +1,286 @@ +/*- + * Copyright (c) 2010,2011 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: binary.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); + +/* + * Convert ELF object to `binary'. Sections with SHF_ALLOC flag set + * are copied to the result binary. The relative offsets for each section + * are retained, so the result binary file might contain "holes". + */ +void +create_binary(int ifd, int ofd) +{ + Elf *e; + Elf_Scn *scn; + Elf_Data *d; + GElf_Shdr sh; + off_t base, off; + int elferr; + + if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + base = 0; + if (lseek(ofd, base, SEEK_SET) < 0) + err(EXIT_FAILURE, "lseek failed"); + + /* + * Find base offset in the first iteration. + */ + base = -1; + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((sh.sh_flags & SHF_ALLOC) == 0 || + sh.sh_type == SHT_NOBITS || + sh.sh_size == 0) + continue; + if (base == -1 || (off_t) sh.sh_offset < base) + base = sh.sh_offset; + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); + + if (base == -1) + return; + + /* + * Write out sections in the second iteration. + */ + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((sh.sh_flags & SHF_ALLOC) == 0 || + sh.sh_type == SHT_NOBITS || + sh.sh_size == 0) + continue; + (void) elf_errno(); + if ((d = elf_getdata(scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + continue; + } + if (d->d_buf == NULL || d->d_size == 0) + continue; + + /* lseek to section offset relative to `base'. */ + off = sh.sh_offset - base; + if (lseek(ofd, off, SEEK_SET) < 0) + err(EXIT_FAILURE, "lseek failed"); + + /* Write out section contents. */ + if (write(ofd, d->d_buf, d->d_size) != (ssize_t) d->d_size) + err(EXIT_FAILURE, "write failed"); + } + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); +} + +#define _SYMBOL_NAMSZ 1024 + +/* + * Convert `binary' to ELF object. The input `binary' is converted to + * a relocatable (.o) file, a few symbols will also be created to make + * it easier to access the binary data in other compilation units. + */ +void +create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn) +{ + char name[_SYMBOL_NAMSZ]; + struct section *sec, *sec_temp, *shtab; + struct stat sb; + GElf_Ehdr oeh; + GElf_Shdr sh; + void *content; + uint64_t off, data_start, data_end, data_size; + + /* Reset internal section list. */ + if (!TAILQ_EMPTY(&ecp->v_sec)) + TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) { + TAILQ_REMOVE(&ecp->v_sec, sec, sec_list); + free(sec); + } + + if (fstat(ifd, &sb) == -1) + err(EXIT_FAILURE, "fstat failed"); + + /* Read the input binary file to a internal buffer. */ + if ((content = malloc(sb.st_size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if (read(ifd, content, sb.st_size) != sb.st_size) + err(EXIT_FAILURE, "read failed"); + + /* + * TODO: copy the input binary to output binary verbatim if -O is not + * specified. + */ + + /* Create EHDR for output .o file. */ + if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) + errx(EXIT_FAILURE, "gelf_newehdr failed: %s", + elf_errmsg(-1)); + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Initialise e_ident fields. */ + oeh.e_ident[EI_CLASS] = ecp->oec; + oeh.e_ident[EI_DATA] = ecp->oed; + /* + * TODO: Set OSABI according to the OS platform where elfcopy(1) + * was build. (probably) + */ + oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; + oeh.e_machine = ecp->oem; + oeh.e_type = ET_REL; + oeh.e_entry = 0; + + ecp->flags |= RELOCATABLE; + + /* Create .shstrtab section */ + init_shstrtab(ecp); + ecp->shstrtab->off = 0; + + /* + * Create `.data' section which contains the binary data. The + * section is inserted immediately after EHDR. + */ + off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); + if (off == 0) + errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); + (void) create_external_section(ecp, ".data", NULL, content, sb.st_size, + off, SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, 0, 1); + + /* Insert .shstrtab after .data section. */ + if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + insert_to_sec_list(ecp, ecp->shstrtab, 1); + + /* Insert section header table here. */ + shtab = insert_shtab(ecp, 1); + + /* Count in .symtab and .strtab section headers. */ + shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT); + +#define _GEN_SYMNAME(S) do { \ + snprintf(name, sizeof(name), "%s%s%s", "_binary_", ifn, S); \ +} while (0) + + /* + * Create symbol table. + */ + create_external_symtab(ecp); + data_start = 0; + data_end = data_start + sb.st_size; + data_size = sb.st_size; + _GEN_SYMNAME("_start"); + add_to_symtab(ecp, name, data_start, 0, 1, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); + _GEN_SYMNAME("_end"); + add_to_symtab(ecp, name, data_end, 0, 1, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); + _GEN_SYMNAME("_size"); + add_to_symtab(ecp, name, data_size, 0, SHN_ABS, + ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); + finalize_external_symtab(ecp); + create_symtab_data(ecp); +#undef _GEN_SYMNAME + + /* + * Write the underlying ehdr. Note that it should be called + * before elf_setshstrndx() since it will overwrite e->e_shstrndx. + */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Generate section name string table (.shstrtab). */ + ecp->flags |= SYMTAB_EXIST; + set_shstrtab(ecp); + + /* Update sh_name pointer for each section header entry. */ + update_shdr(ecp, 0); + + /* Properly set sh_link field of .symtab section. */ + if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) + errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", + elf_errmsg(-1)); + sh.sh_link = elf_ndxscn(ecp->strtab->os); + if (!gelf_update_shdr(ecp->symtab->os, &sh)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + + /* Renew oeh to get the updated e_shstrndx. */ + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* Resync section offsets. */ + resync_sections(ecp); + + /* Store SHDR offset in EHDR. */ + oeh.e_shoff = shtab->off; + + /* Update ehdr since we modified e_shoff. */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Write out the output elf object. */ + if (elf_update(ecp->eout, ELF_C_WRITE) < 0) + errx(EXIT_FAILURE, "elf_update() failed: %s", + elf_errmsg(-1)); + + /* Release allocated resource. */ + free(content); + free_elf(ecp); +} diff --git a/contrib/elftoolchain/elfcopy/elfcopy.1 b/contrib/elftoolchain/elfcopy/elfcopy.1 new file mode 100644 index 000000000000..2976da377d2b --- /dev/null +++ b/contrib/elftoolchain/elfcopy/elfcopy.1 @@ -0,0 +1,323 @@ +.\" Copyright (c) 2008-2009,2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elfcopy.1 2373 2011-12-30 07:13:44Z jkoshy $ +.\" +.Dd October 03, 2011 +.Os +.Dt ELFCOPY 1 +.Sh NAME +.Nm elfcopy +.Nd copy and translate object files +.Sh SYNOPSIS +.Nm +.Op Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat +.Op Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname +.Op Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname +.Op Fl N Ar symbolname | Fl -strip-symbol= Ns Ar symbolname +.Op Fl O Ar objformat | Fl -output-target= Ns Ar objformat +.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname +.Op Fl S | Fl -strip-all +.Op Fl V | Fl -version +.Op Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname +.Op Fl X | Fl -discard-locals +.Op Fl d | Fl g | Fl -strip-debug +.Op Fl h | Fl -help +.Op Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname +.Op Fl p | Fl -preserve-dates +.Op Fl w | Fl -wildcard +.Op Fl x | Fl -discard-all +.Op Fl -add-section Ar sectionname Ns = Ns Ar filename +.Oo +.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val | +.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val +.Oc +.Oo +.Fl -adjust-start Ns = Ns Ar increment | +.Fl -change-start Ns = Ns Ar increment +.Oc +.Oo +.Fl -adjust-vma Ns = Ns Ar increment | +.Fl -change-addresses Ns = Ns Ar increment +.Oc +.Op Fl -adjust-warnings | Fl -change-warnings +.Op Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val +.Op Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val +.Op Fl -gap-fill Ns = Ns Ar val +.Op Fl -no-adjust-warnings | Fl -no-change-warnings +.Op Fl -only-keep-debug +.Op Fl -pad-to Ns = Ns Ar address +.Op Fl -prefix-alloc-sections Ns = Ns Ar string +.Op Fl -prefix-sections Ns = Ns Ar string +.Op Fl -prefix-symbols Ns = Ns Ar string +.Op Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags +.Op Fl -set-section-flags Ar sectionname Ns = Ns Ar flags +.Op Fl -set-start Ns = Ns Ar address +.Op Fl -srec-forceS3 +.Op Fl -srec-len Ns = Ns Ar val +.Op Fl -strip-unneeded +.Ar infile +.Op Ar outfile +.Sh DESCRIPTION +The +.Nm +utility copies the content of the ELF object named by argument +.Ar infile +to that named by argument +.Ar outfile , +transforming it according to the command line options specified. +If argument +.Ar outfile +is not specified, +.Nm +will create a temporary file and will subsequently rename it as +.Ar infile . +.Pp +The +.Nm +utility supports the following options: +.Bl -tag -width indent +.It Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat +Specify that the input file named by the argument +.Ar infile +is in the object format specified by the argument +.Ar objformat . +.It Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname +Copy the symbol named by argument +.Ar symbolname +to the output. +.It Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname +Make the symbol named by argument +.Ar symbolname +local to the output file. +.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbolname +Do not copy the symbol named by argument +.Ar symbolname +to the output. +.It Fl O Ar objformat | Fl -output-target= Ns Ar objformat +Write the output file using the object format specified in argument +.Ar objformat . +.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname +Remove any section with name +.Ar sectionname +from the output file. +.It Fl S | Fl -strip-all +Do not copy symbol and relocation information to the target file. +.It Fl V | Fl -version +Print a version identifier and exit. +.It Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname +Mark the symbol named by argument +.Ar symbolname +as weak in the output. +.It Fl X | Fl -discard-locals +Do not copy compiler generated local symbols to the output. +.It Fl d | Fl g | Fl -strip-debug +Do not copy debugging information to the target file. +.It Fl h | Fl -help +Display a help message and exit. +.It Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname +Copy only the section named by argument +.Ar sectionname +to the output. +.It Fl p | Fl -preserve-dates +Set the access and modification times of the output file to the +same as those of the input. +.It Fl w | Fl -wildcard +Use shell-style patterns to name symbols. +The following meta-characters are recognized in patterns: +.Bl -tag -width "...." -compact +.It Li ! +If this is the first character of the pattern, invert the sense of the +pattern match. +.It Li * +Matches any string of characters in a symbol name. +.It Li ? +Matches zero or one character in a symbol name. +.It Li [ +Mark the start of a character class. +.It Li \e +Remove the special meaning of the next character in the pattern. +.It Li ] +Mark the end of a character class. +.El +.It Fl x | Fl -discard-all +Do not copy non-global symbols to the output. +.It Fl -add-section Ar sectionname Ns = Ns Ar filename +Add a new section to the output file with name +.Ar sectionname . +The contents of the section are taken from the file named by +argument +.Ar filename . +The size of the section will be the number of bytes in file +.Ar filename . +.It Xo +.Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val | +.Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val +.Xc +Depending on the operator specified, increase, decrease or set both +the virtual memory address and the load memory address of the section +named by the argument +.Ar section . +The argument +.Ar val +specifies the desired increment, decrement or new value for the +address. +.It Xo +.Fl -adjust-start Ns = Ns Ar increment | +.Fl -change-start Ns = Ns Ar increment +.Xc +Increase the entry point address of the output ELF object by the value +specified in the argument +.Ar increment . +.It Xo +.Fl -adjust-vma Ns = Ns Ar increment | +.Fl -change-addresses Ns = Ns Ar increment +.Xc +Increase the virtual memory address and the load memory address of all +sections by the value specified by the argument +.Ar increment . +.It Fl -adjust-warnings | Fl -change-warnings +Issue a warning if the section specified by the options +.Fl -change-section-address , +.Fl -change-section-lma +or +.Fl -change-section-vma +does not exist in the input object. +This is the default. +.It Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val +Change or set the load memory address of the section named by the +argument +.Ar section . +Depending on the operator specified, the value in argument +.Ar val +will be used as an increment, a decrement or as the new value +of the load memory address. +.It Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val +Change or set the virtual memory address of the section named by the +argument +.Ar section . +Depending on the operator specified, the value in argument +.Ar val +will be used as an increment, a decrement or as the new value +of the virtual memory address. +.It Fl -gap-fill Ns = Ns Ar val +Fill the gaps between sections with the byte value specified by +the argument +.Ar val . +.It Fl -no-adjust-warnings | Fl -no-change-warnings +Do not issue a warning if the section specified by the options +.Fl -change-section-address , +.Fl -change-section-lma +or +.Fl -change-section-vma +is missing in the input object. +.It Fl -only-keep-debug +Copy only debugging information to the output file. +.It Fl -pad-to Ns = Ns Ar address +Pad the load memory address of the output object to the value +specified by the argument +.Ar address +by increasing the size of the section with the highest load memory +address. +.It Fl -prefix-alloc-sections Ns = Ns Ar string +Prefix the section names of all the allocated sections with +.Ar string . +.It Fl -prefix-sections Ns = Ns Ar string +Prefix the section names of all the sections with +.Ar string . +.It Fl -prefix-symbols Ns = Ns Ar string +Prefix the symbol names of all the symbols with +.Ar string . +.It Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags +Rename the section named by argument +.Ar oldname +to +.Ar newname , +optionally changing the sections flags to that specified by argument +.Ar flags . +Allowed values for the argument +.Ar flags +are as for option +.Fl -set-section-flags +below. +.It Fl -set-section-flags Ar sectionname Ns = Ns Ar flags +Set the flags for the section named by argument +.Ar sectionname +to those specified by argument +.Ar flags . +Argument +.Ar flags +is a comma separated list of the following flag names: +.Bl -tag -width "readonly" -compact +.It alloc +The section occupies space in the output file. +.It code +The section contains machine instructions. +.It contents +This flag is accepted but is ignored. +.It data +The section contains writeable data. +.It debug +The section holds debugging information. +.It load +The section is loadable. +.It noload +The section should not be loaded into memory. +.It readonly +The section is not writable. +.It rom +The section contains ROM'able contents. +.It share +This flag is accepted but is ignored. +.El +.It Fl -set-start Ns = Ns Ar address +Set the start address of the output ELF object to the value specified +by the argument +.Ar address . +.It Fl -srec-forceS3 +Only generate S-records of type +.Dq S3 . +This option is only meaningful when the output target is set to +.Dq srec . +.It Fl -srec-len Ns = Ns Ar val +Set the maximum length of an S-record line to +.Ar val . +This option is only meaningful when the output target is set to +.Dq srec . +.It Fl -strip-unneeded +Do not copy symbols that are not needed for relocation processing. +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr ar 1 , +.Xr ld 1 , +.Xr mcs 1 , +.Xr strip 1 , +.Xr elf 3 , +.Xr ar 5 , +.Xr elf 5 +.Sh HISTORY +.Nm +has been implemented by +.An "Kai Wang" Aq kaiwang27@users.sourceforge.net . diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h new file mode 100644 index 000000000000..609e2916f527 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/elfcopy.h @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 2007-2013 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: elfcopy.h 2970 2013-12-01 15:22:12Z kaiwang27 $ + */ + +#include +#include +#include + +#include "_elftc.h" + +/* + * User specified symbol operation (strip, keep, localize, globalize, + * weaken, rename, etc). + */ +struct symop { + const char *name; + const char *newname; + +#define SYMOP_KEEP 0x0001U +#define SYMOP_STRIP 0x0002U +#define SYMOP_GLOBALIZE 0x0004U +#define SYMOP_LOCALIZE 0x0008U +#define SYMOP_KEEPG 0x0010U +#define SYMOP_WEAKEN 0x0020U +#define SYMOP_REDEF 0x0040U + + unsigned int op; + + STAILQ_ENTRY(symop) symop_list; +}; + +/* File containing symbol list. */ +struct symfile { + dev_t dev; + ino_t ino; + size_t size; + char *data; + unsigned int op; + + STAILQ_ENTRY(symfile) symfile_list; +}; + +/* Sections to copy/remove/rename/... */ +struct sec_action { + const char *name; + const char *addopt; + const char *newname; + const char *string; + uint64_t lma; + uint64_t vma; + int64_t lma_adjust; + int64_t vma_adjust; + +#define SF_ALLOC 0x0001U +#define SF_LOAD 0x0002U +#define SF_NOLOAD 0x0004U +#define SF_READONLY 0x0008U +#define SF_DEBUG 0x0010U +#define SF_CODE 0x0020U +#define SF_DATA 0x0040U +#define SF_ROM 0x0080U +#define SF_SHARED 0X0100U +#define SF_CONTENTS 0x0200U + + int flags; + int add; + int append; + int compress; + int copy; + int print; + int remove; + int rename; + int setflags; + int setlma; + int setvma; + + STAILQ_ENTRY(sec_action) sac_list; +}; + +/* Sections to add from file. */ +struct sec_add { + char *name; + char *content; + size_t size; + + STAILQ_ENTRY(sec_add) sadd_list; +}; + +struct segment; + +/* Internal data structure for sections. */ +struct section { + struct segment *seg; /* containing segment */ + const char *name; /* section name */ + char *newname; /* new section name */ + Elf_Scn *is; /* input scn */ + Elf_Scn *os; /* output scn */ + void *buf; /* section content */ + uint8_t *pad; /* section padding */ + uint64_t off; /* section offset */ + uint64_t sz; /* section size */ + uint64_t cap; /* section capacity */ + uint64_t align; /* section alignment */ + uint64_t type; /* section type */ + uint64_t vma; /* section virtual addr */ + uint64_t lma; /* section load addr */ + uint64_t pad_sz;/* section padding size */ + int loadable; /* whether loadable */ + int pseudo; + int nocopy; + + TAILQ_ENTRY(section) sec_list; /* next section */ +}; + +/* Internal data structure for segments. */ +struct segment { + uint64_t addr; /* load addr */ + uint64_t off; /* file offset */ + uint64_t fsz; /* file size */ + uint64_t msz; /* memory size */ + uint64_t type; /* segment type */ + int remove; /* whether remove */ + int nsec; /* number of sections contained */ + struct section **v_sec; /* list of sections contained */ + + STAILQ_ENTRY(segment) seg_list; /* next segment */ +}; + +/* + * In-memory representation of ar(1) archive member(object). + */ +struct ar_obj { + char *name; /* member name */ + char *buf; /* member content */ + void *maddr; /* mmap start address */ + uid_t uid; /* user id */ + gid_t gid; /* group id */ + mode_t md; /* octal file permissions */ + size_t size; /* member size */ + time_t mtime; /* modification time */ + + STAILQ_ENTRY(ar_obj) objs; +}; + +/* + * Structure encapsulates the "global" data for "elfcopy" program. + */ +struct elfcopy { + const char *progname; /* program name */ + int iec; /* elfclass of input object */ + Elftc_Bfd_Target_Flavor itf; /* flavour of input object */ + Elftc_Bfd_Target_Flavor otf; /* flavour of output object */ + const char *otgt; /* output target name */ + int oec; /* elfclass of output object */ + unsigned char oed; /* endianess of output object */ + int oem; /* EM_XXX of output object */ + int abi; /* OSABI of output object */ + Elf *ein; /* ELF descriptor of input object */ + Elf *eout; /* ELF descriptor of output object */ + int iphnum; /* num. of input object phdr entries */ + int ophnum; /* num. of output object phdr entries */ + int nos; /* num. of output object sections */ + + enum { + STRIP_NONE = 0, + STRIP_ALL, + STRIP_DEBUG, + STRIP_NONDEBUG, + STRIP_UNNEEDED + } strip; + +#define EXECUTABLE 0x00000001U +#define DYNAMIC 0x00000002U +#define RELOCATABLE 0x00000004U +#define SYMTAB_EXIST 0x00000010U +#define SYMTAB_INTACT 0x00000020U +#define KEEP_GLOBAL 0x00000040U +#define DISCARD_LOCAL 0x00000080U +#define WEAKEN_ALL 0x00000100U +#define PRESERVE_DATE 0x00001000U +#define SREC_FORCE_S3 0x00002000U +#define SREC_FORCE_LEN 0x00004000U +#define SET_START 0x00008000U +#define GAP_FILL 0x00010000U +#define WILDCARD 0x00020000U +#define NO_CHANGE_WARN 0x00040000U +#define SEC_ADD 0x00080000U +#define SEC_APPEND 0x00100000U +#define SEC_COMPRESS 0x00200000U +#define SEC_PRINT 0x00400000U +#define SEC_REMOVE 0x00800000U +#define SEC_COPY 0x01000000U +#define DISCARD_LLABEL 0x02000000U + + int flags; /* elfcopy run control flags. */ + int64_t change_addr; /* Section address adjustment. */ + int64_t change_start; /* Entry point adjustment. */ + uint64_t set_start; /* Entry point value. */ + unsigned long srec_len; /* S-Record length. */ + uint64_t pad_to; /* load address padding. */ + uint8_t fill; /* gap fill value. */ + char *prefix_sec; /* section prefix. */ + char *prefix_alloc; /* alloc section prefix. */ + char *prefix_sym; /* symbol prefix. */ + char *debuglink; /* GNU debuglink file. */ + struct section *symtab; /* .symtab section. */ + struct section *strtab; /* .strtab section. */ + struct section *shstrtab; /* .shstrtab section. */ + uint64_t *secndx; /* section index map. */ + uint64_t *symndx; /* symbol index map. */ + unsigned char *v_rel; /* symbols needed by relocation. */ + unsigned char *v_secsym; /* sections with section symbol. */ + STAILQ_HEAD(, segment) v_seg; /* list of segments. */ + STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */ + STAILQ_HEAD(, sec_add) v_sadd; /* list of sections to add. */ + STAILQ_HEAD(, symop) v_symop; /* list of symbols operations. */ + STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */ + TAILQ_HEAD(, section) v_sec; /* list of sections. */ + + /* + * Fields for the ar(1) archive. + */ + char *as; /* buffer for archive string table. */ + size_t as_sz; /* current size of as table. */ + size_t as_cap; /* capacity of as table buffer. */ + uint32_t s_cnt; /* current number of symbols. */ + uint32_t *s_so; /* symbol offset table. */ + size_t s_so_cap; /* capacity of so table buffer. */ + char *s_sn; /* symbol name table */ + size_t s_sn_cap; /* capacity of sn table buffer. */ + size_t s_sn_sz; /* current size of sn table. */ + off_t rela_off; /* offset relative to pseudo members. */ + STAILQ_HEAD(, ar_obj) v_arobj; /* archive object(member) list. */ +}; + +void add_section(struct elfcopy *_ecp, const char *_optarg); +void add_to_shstrtab(struct elfcopy *_ecp, const char *_name); +void add_to_symop_list(struct elfcopy *_ecp, const char *_name, + const char *_newname, unsigned int _op); +void add_to_symtab(struct elfcopy *_ecp, const char *_name, + uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx, + unsigned char _st_info, unsigned char _st_other, int _ndx_known); +int add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec); +void adjust_addr(struct elfcopy *_ecp); +void copy_content(struct elfcopy *_ecp); +void copy_data(struct section *_s); +void copy_phdr(struct elfcopy *_ecp); +void copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name, + int _copy, int _sec_flags); +void create_binary(int _ifd, int _ofd); +void create_elf(struct elfcopy *_ecp); +void create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn); +void create_elf_from_ihex(struct elfcopy *_ecp, int _ifd); +void create_elf_from_srec(struct elfcopy *_ecp, int _ifd); +struct section *create_external_section(struct elfcopy *_ecp, const char *_name, + char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype, + Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma, + int _loadable); +void create_external_symtab(struct elfcopy *_ecp); +void create_ihex(int _ifd, int _ofd); +void create_scn(struct elfcopy *_ecp); +void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn); +void create_symtab(struct elfcopy *_ecp); +void create_symtab_data(struct elfcopy *_ecp); +void create_tempfile(char **_fn, int *_fd); +void finalize_external_symtab(struct elfcopy *_ecp); +void free_elf(struct elfcopy *_ecp); +void free_sec_act(struct elfcopy *_ecp); +void free_sec_add(struct elfcopy *_ecp); +void free_symtab(struct elfcopy *_ecp); +void init_shstrtab(struct elfcopy *_ecp); +void insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec, + int _tail); +struct section *insert_shtab(struct elfcopy *_ecp, int tail); +int is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info); +int is_remove_section(struct elfcopy *_ecp, const char *_name); +struct sec_action *lookup_sec_act(struct elfcopy *_ecp, + const char *_name, int _add); +struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name, + unsigned int _op); +void resync_sections(struct elfcopy *_ecp); +void set_shstrtab(struct elfcopy *_ecp); +void setup_phdr(struct elfcopy *_ecp); +void update_shdr(struct elfcopy *_ecp, int _update_link); + +#ifndef LIBELF_AR +int ac_detect_ar(int _ifd); +void ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd); +#endif /* ! LIBELF_AR */ diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c new file mode 100644 index 000000000000..3689f355fecd --- /dev/null +++ b/contrib/elftoolchain/elfcopy/main.c @@ -0,0 +1,1500 @@ +/*- + * Copyright (c) 2007-2013 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: main.c 2970 2013-12-01 15:22:12Z kaiwang27 $"); + +enum options +{ + ECP_ADD_GNU_DEBUGLINK, + ECP_ADD_SECTION, + ECP_CHANGE_ADDR, + ECP_CHANGE_SEC_ADDR, + ECP_CHANGE_SEC_LMA, + ECP_CHANGE_SEC_VMA, + ECP_CHANGE_START, + ECP_CHANGE_WARN, + ECP_GAP_FILL, + ECP_GLOBALIZE_SYMBOL, + ECP_GLOBALIZE_SYMBOLS, + ECP_KEEP_SYMBOLS, + ECP_KEEP_GLOBAL_SYMBOLS, + ECP_LOCALIZE_SYMBOLS, + ECP_NO_CHANGE_WARN, + ECP_ONLY_DEBUG, + ECP_PAD_TO, + ECP_PREFIX_ALLOC, + ECP_PREFIX_SEC, + ECP_PREFIX_SYM, + ECP_REDEF_SYMBOL, + ECP_REDEF_SYMBOLS, + ECP_RENAME_SECTION, + ECP_SET_OSABI, + ECP_SET_SEC_FLAGS, + ECP_SET_START, + ECP_SREC_FORCE_S3, + ECP_SREC_LEN, + ECP_STRIP_SYMBOLS, + ECP_STRIP_UNNEEDED, + ECP_WEAKEN_ALL, + ECP_WEAKEN_SYMBOLS +}; + +static struct option mcs_longopts[] = +{ + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +static struct option strip_longopts[] = +{ + {"discard-all", no_argument, NULL, 'x'}, + {"discard-locals", no_argument, NULL, 'X'}, + {"help", no_argument, NULL, 'h'}, + {"input-target", required_argument, NULL, 'I'}, + {"keep-symbol", required_argument, NULL, 'K'}, + {"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG}, + {"output-file", required_argument, NULL, 'o'}, + {"output-target", required_argument, NULL, 'O'}, + {"preserve-dates", no_argument, NULL, 'p'}, + {"remove-section", required_argument, NULL, 'R'}, + {"strip-all", no_argument, NULL, 's'}, + {"strip-debug", no_argument, NULL, 'S'}, + {"strip-symbol", required_argument, NULL, 'N'}, + {"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED}, + {"version", no_argument, NULL, 'V'}, + {"wildcard", no_argument, NULL, 'w'}, + {NULL, 0, NULL, 0} +}; + +static struct option elfcopy_longopts[] = +{ + {"add-gnu-debuglink", required_argument, NULL, ECP_ADD_GNU_DEBUGLINK}, + {"add-section", required_argument, NULL, ECP_ADD_SECTION}, + {"adjust-section-vma", required_argument, NULL, ECP_CHANGE_SEC_ADDR}, + {"adjust-vma", required_argument, NULL, ECP_CHANGE_ADDR}, + {"adjust-start", required_argument, NULL, ECP_CHANGE_START}, + {"adjust-warnings", no_argument, NULL, ECP_CHANGE_WARN}, + {"binary-architecture", required_argument, NULL, 'B'}, + {"change-addresses", required_argument, NULL, ECP_CHANGE_ADDR}, + {"change-section-address", required_argument, NULL, + ECP_CHANGE_SEC_ADDR}, + {"change-section-lma", required_argument, NULL, ECP_CHANGE_SEC_LMA}, + {"change-section-vma", required_argument, NULL, ECP_CHANGE_SEC_VMA}, + {"change-start", required_argument, NULL, ECP_CHANGE_START}, + {"change-warnings", no_argument, NULL, ECP_CHANGE_WARN}, + {"discard-all", no_argument, NULL, 'x'}, + {"discard-locals", no_argument, NULL, 'X'}, + {"gap-fill", required_argument, NULL, ECP_GAP_FILL}, + {"globalize-symbol", required_argument, NULL, ECP_GLOBALIZE_SYMBOL}, + {"globalize-symbols", required_argument, NULL, ECP_GLOBALIZE_SYMBOLS}, + {"help", no_argument, NULL, 'h'}, + {"input-target", required_argument, NULL, 'I'}, + {"keep-symbol", required_argument, NULL, 'K'}, + {"keep-symbols", required_argument, NULL, ECP_KEEP_SYMBOLS}, + {"keep-global-symbol", required_argument, NULL, 'G'}, + {"keep-global-symbols", required_argument, NULL, + ECP_KEEP_GLOBAL_SYMBOLS}, + {"localize-symbol", required_argument, NULL, 'L'}, + {"localize-symbols", required_argument, NULL, ECP_LOCALIZE_SYMBOLS}, + {"no-adjust-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN}, + {"no-change-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN}, + {"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG}, + {"only-section", required_argument, NULL, 'j'}, + {"osabi", required_argument, NULL, ECP_SET_OSABI}, + {"output-target", required_argument, NULL, 'O'}, + {"pad-to", required_argument, NULL, ECP_PAD_TO}, + {"preserve-dates", no_argument, NULL, 'p'}, + {"prefix-alloc-sections", required_argument, NULL, ECP_PREFIX_ALLOC}, + {"prefix-sections", required_argument, NULL, ECP_PREFIX_SEC}, + {"prefix-symbols", required_argument, NULL, ECP_PREFIX_SYM}, + {"redefine-sym", required_argument, NULL, ECP_REDEF_SYMBOL}, + {"redefine-syms", required_argument, NULL, ECP_REDEF_SYMBOLS}, + {"remove-section", required_argument, NULL, 'R'}, + {"rename-section", required_argument, NULL, ECP_RENAME_SECTION}, + {"set-section-flags", required_argument, NULL, ECP_SET_SEC_FLAGS}, + {"set-start", required_argument, NULL, ECP_SET_START}, + {"srec-forceS3", no_argument, NULL, ECP_SREC_FORCE_S3}, + {"srec-len", required_argument, NULL, ECP_SREC_LEN}, + {"strip-all", no_argument, NULL, 'S'}, + {"strip-debug", no_argument, 0, 'g'}, + {"strip-symbol", required_argument, NULL, 'N'}, + {"strip-symbols", required_argument, NULL, ECP_STRIP_SYMBOLS}, + {"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED}, + {"version", no_argument, NULL, 'V'}, + {"weaken", no_argument, NULL, ECP_WEAKEN_ALL}, + {"weaken-symbol", required_argument, NULL, 'W'}, + {"weaken-symbols", required_argument, NULL, ECP_WEAKEN_SYMBOLS}, + {"wildcard", no_argument, NULL, 'w'}, + {NULL, 0, NULL, 0} +}; + +static struct { + const char *name; + int value; +} sec_flags[] = { + {"alloc", SF_ALLOC}, + {"load", SF_LOAD}, + {"noload", SF_NOLOAD}, + {"readonly", SF_READONLY}, + {"debug", SF_DEBUG}, + {"code", SF_CODE}, + {"data", SF_DATA}, + {"rom", SF_ROM}, + {"share", SF_SHARED}, + {"contents", SF_CONTENTS}, + {NULL, 0} +}; + +static struct { + const char *name; + int abi; +} osabis[] = { + {"sysv", ELFOSABI_SYSV}, + {"hpus", ELFOSABI_HPUX}, + {"netbsd", ELFOSABI_NETBSD}, + {"linux", ELFOSABI_LINUX}, + {"hurd", ELFOSABI_HURD}, + {"86open", ELFOSABI_86OPEN}, + {"solaris", ELFOSABI_SOLARIS}, + {"aix", ELFOSABI_AIX}, + {"irix", ELFOSABI_IRIX}, + {"freebsd", ELFOSABI_FREEBSD}, + {"tru64", ELFOSABI_TRU64}, + {"modesto", ELFOSABI_MODESTO}, + {"openbsd", ELFOSABI_OPENBSD}, + {"openvms", ELFOSABI_OPENVMS}, + {"nsk", ELFOSABI_NSK}, + {"arm", ELFOSABI_ARM}, + {"standalone", ELFOSABI_STANDALONE}, + {NULL, 0} +}; + +static int copy_from_tempfile(const char *src, const char *dst, + int infd, int *outfd); +static void create_file(struct elfcopy *ecp, const char *src, + const char *dst); +static void elfcopy_main(struct elfcopy *ecp, int argc, char **argv); +static void elfcopy_usage(void); +static void mcs_main(struct elfcopy *ecp, int argc, char **argv); +static void mcs_usage(void); +static void parse_sec_address_op(struct elfcopy *ecp, int optnum, + const char *optname, char *s); +static void parse_sec_flags(struct sec_action *sac, char *s); +static void parse_symlist_file(struct elfcopy *ecp, const char *fn, + unsigned int op); +static void print_version(void); +static void set_input_target(struct elfcopy *ecp, const char *target_name); +static void set_osabi(struct elfcopy *ecp, const char *abi); +static void set_output_target(struct elfcopy *ecp, const char *target_name); +static void strip_main(struct elfcopy *ecp, int argc, char **argv); +static void strip_usage(void); + +/* + * An ELF object usually has a sturcture described by the + * diagram below. + * _____________ + * | | + * | NULL | <- always a SHT_NULL section + * |_____________| + * | | + * | .interp | + * |_____________| + * | | + * | ... | + * |_____________| + * | | + * | .text | + * |_____________| + * | | + * | ... | + * |_____________| + * | | + * | .comment | <- above(include) this: normal sections + * |_____________| + * | | + * | add sections| <- unloadable sections added by --add-section + * |_____________| + * | | + * | .shstrtab | <- section name string table + * |_____________| + * | | + * | shdrs | <- section header table + * |_____________| + * | | + * | .symtab | <- symbol table, if any + * |_____________| + * | | + * | .strtab | <- symbol name string table, if any + * |_____________| + * | | + * | .rel.text | <- relocation info for .o files. + * |_____________| + */ +void +create_elf(struct elfcopy *ecp) +{ + struct section *shtab; + GElf_Ehdr ieh; + GElf_Ehdr oeh; + size_t ishnum; + + ecp->flags |= SYMTAB_INTACT; + + /* Create EHDR. */ + if (gelf_getehdr(ecp->ein, &ieh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + if ((ecp->iec = gelf_getclass(ecp->ein)) == ELFCLASSNONE) + errx(EXIT_FAILURE, "getclass() failed: %s", + elf_errmsg(-1)); + + if (ecp->oec == ELFCLASSNONE) + ecp->oec = ecp->iec; + if (ecp->oed == ELFDATANONE) + ecp->oed = ieh.e_ident[EI_DATA]; + + if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) + errx(EXIT_FAILURE, "gelf_newehdr failed: %s", + elf_errmsg(-1)); + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + memcpy(oeh.e_ident, ieh.e_ident, sizeof(ieh.e_ident)); + oeh.e_ident[EI_CLASS] = ecp->oec; + oeh.e_ident[EI_DATA] = ecp->oed; + if (ecp->abi != -1) + oeh.e_ident[EI_OSABI] = ecp->abi; + oeh.e_flags = ieh.e_flags; + oeh.e_machine = ieh.e_machine; + oeh.e_type = ieh.e_type; + oeh.e_entry = ieh.e_entry; + oeh.e_version = ieh.e_version; + + if (ieh.e_type == ET_EXEC) + ecp->flags |= EXECUTABLE; + else if (ieh.e_type == ET_DYN) + ecp->flags |= DYNAMIC; + else if (ieh.e_type == ET_REL) + ecp->flags |= RELOCATABLE; + else + errx(EXIT_FAILURE, "unsupported e_type"); + + if (!elf_getshnum(ecp->ein, &ishnum)) + errx(EXIT_FAILURE, "elf_getshnum failed: %s", + elf_errmsg(-1)); + if (ishnum > 0 && (ecp->secndx = calloc(ishnum, + sizeof(*ecp->secndx))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + + /* Read input object program header. */ + setup_phdr(ecp); + + /* + * Scan of input sections: we iterate through sections from input + * object, skip sections need to be stripped, allot Elf_Scn and + * create internal section structure for sections we want. + * (i.e., determine output sections) + */ + create_scn(ecp); + + /* Apply section address changes, if any. */ + adjust_addr(ecp); + + /* + * Determine if the symbol table needs to be changed based on + * command line options. + */ + if (ecp->strip == STRIP_DEBUG || + ecp->strip == STRIP_UNNEEDED || + ecp->flags & WEAKEN_ALL || + ecp->flags & DISCARD_LOCAL || + ecp->flags & DISCARD_LLABEL || + ecp->prefix_sym != NULL || + !STAILQ_EMPTY(&ecp->v_symop)) + ecp->flags &= ~SYMTAB_INTACT; + + /* + * Create symbol table. Symbols are filtered or stripped according to + * command line args specified by user, and later updated for the new + * layout of sections in the output object. + */ + if ((ecp->flags & SYMTAB_EXIST) != 0) + create_symtab(ecp); + + /* + * First processing of output sections: at this stage we copy the + * content of each section from input to output object. Section + * content will be modified and printed (mcs) if need. Also content of + * relocation section probably will be filtered and updated according + * to symbol table changes. + */ + copy_content(ecp); + + /* + * Write the underlying ehdr. Note that it should be called + * before elf_setshstrndx() since it will overwrite e->e_shstrndx. + */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + /* Generate section name string table (.shstrtab). */ + set_shstrtab(ecp); + + /* + * Second processing of output sections: Update section headers. + * At this stage we set name string index, update st_link and st_info + * for output sections. + */ + update_shdr(ecp, 1); + + /* Renew oeh to get the updated e_shstrndx. */ + if (gelf_getehdr(ecp->eout, &oeh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* + * Insert SHDR table into the internal section list as a "pseudo" + * section, so later it will get sorted and resynced just as "normal" + * sections. + */ + shtab = insert_shtab(ecp, 0); + + /* + * Resync section offsets in the output object. This is needed + * because probably sections are modified or new sections are added, + * as a result overlap/gap might appears. + */ + resync_sections(ecp); + + /* Store SHDR offset in EHDR. */ + oeh.e_shoff = shtab->off; + + /* Put program header table immediately after the Elf header. */ + if (ecp->ophnum > 0) { + oeh.e_phoff = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); + if (oeh.e_phoff == 0) + errx(EXIT_FAILURE, "gelf_fsize() failed: %s", + elf_errmsg(-1)); + } + + /* + * Update ELF object entry point if requested. + */ + if (ecp->change_addr != 0) + oeh.e_entry += ecp->change_addr; + if (ecp->flags & SET_START) + oeh.e_entry = ecp->set_start; + if (ecp->change_start != 0) + oeh.e_entry += ecp->change_start; + + /* + * Update ehdr again before we call elf_update(), since we + * modified e_shoff and e_phoff. + */ + if (gelf_update_ehdr(ecp->eout, &oeh) == 0) + errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", + elf_errmsg(-1)); + + if (ecp->ophnum > 0) + copy_phdr(ecp); + + /* Write out the output elf object. */ + if (elf_update(ecp->eout, ELF_C_WRITE) < 0) + errx(EXIT_FAILURE, "elf_update() failed: %s", + elf_errmsg(-1)); + + /* Release allocated resource. */ + free_elf(ecp); +} + +void +free_elf(struct elfcopy *ecp) +{ + struct segment *seg, *seg_temp; + struct section *sec, *sec_temp; + + /* Free internal segment list. */ + if (!STAILQ_EMPTY(&ecp->v_seg)) { + STAILQ_FOREACH_SAFE(seg, &ecp->v_seg, seg_list, seg_temp) { + STAILQ_REMOVE(&ecp->v_seg, seg, segment, seg_list); + free(seg); + } + } + + /* Free symbol table buffers. */ + free_symtab(ecp); + + /* Free internal section list. */ + if (!TAILQ_EMPTY(&ecp->v_sec)) { + TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) { + TAILQ_REMOVE(&ecp->v_sec, sec, sec_list); + if (sec->buf != NULL) + free(sec->buf); + if (sec->newname != NULL) + free(sec->newname); + if (sec->pad != NULL) + free(sec->pad); + free(sec); + } + } +} + +/* Create a temporary file. */ +void +create_tempfile(char **fn, int *fd) +{ + const char *tmpdir; + char *cp, *tmpf; + size_t tlen, plen; + +#define _TEMPFILE "ecp.XXXXXXXX" +#define _TEMPFILEPATH "/tmp/ecp.XXXXXXXX" + + if (fn == NULL || fd == NULL) + return; + /* Repect TMPDIR environment variable. */ + tmpdir = getenv("TMPDIR"); + if (tmpdir != NULL && *tmpdir != '\0') { + tlen = strlen(tmpdir); + plen = strlen(_TEMPFILE); + tmpf = malloc(tlen + plen + 2); + if (tmpf == NULL) + err(EXIT_FAILURE, "malloc failed"); + strncpy(tmpf, tmpdir, tlen); + cp = &tmpf[tlen - 1]; + if (*cp++ != '/') + *cp++ = '/'; + strncpy(cp, _TEMPFILE, plen); + cp[plen] = '\0'; + } else { + tmpf = strdup(_TEMPFILEPATH); + if (tmpf == NULL) + err(EXIT_FAILURE, "strdup failed"); + } + if ((*fd = mkstemp(tmpf)) == -1) + err(EXIT_FAILURE, "mkstemp %s failed", tmpf); + if (fchmod(*fd, 0644) == -1) + err(EXIT_FAILURE, "fchmod %s failed", tmpf); + *fn = tmpf; + +#undef _TEMPFILE +#undef _TEMPFILEPATH +} + +static int +copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd) +{ + int tmpfd; + + /* + * First, check if we can use rename(). + */ + if (rename(src, dst) >= 0) { + *outfd = infd; + return (0); + } else if (errno != EXDEV) + return (-1); + + /* + * If the rename() failed due to 'src' and 'dst' residing in + * two different file systems, invoke a helper function in + * libelftc to do the copy. + */ + + if (unlink(dst) < 0) + return (-1); + + if ((tmpfd = open(dst, O_CREAT | O_WRONLY, 0755)) < 0) + return (-1); + + if (lseek(infd, 0, SEEK_SET) < 0) + return (-1); + + if (elftc_copyfile(infd, tmpfd) < 0) + return (-1); + + /* + * Remove the temporary file from the file system + * namespace, and close its file descriptor. + */ + if (unlink(src) < 0) + return (-1); + + (void) close(infd); + + /* + * Return the file descriptor for the destination. + */ + *outfd = tmpfd; + + return (0); +} + +static void +create_file(struct elfcopy *ecp, const char *src, const char *dst) +{ + struct stat sb; + char *tempfile, *elftemp; + int efd, ifd, ofd, ofd0, tfd; + + tempfile = NULL; + + if (src == NULL) + errx(EXIT_FAILURE, "internal: src == NULL"); + if ((ifd = open(src, O_RDONLY)) == -1) + err(EXIT_FAILURE, "open %s failed", src); + + if (fstat(ifd, &sb) == -1) + err(EXIT_FAILURE, "fstat %s failed", src); + + if (dst == NULL) + create_tempfile(&tempfile, &ofd); + else + if ((ofd = open(dst, O_RDWR|O_CREAT, 0755)) == -1) + err(EXIT_FAILURE, "open %s failed", dst); + +#ifndef LIBELF_AR + /* Detect and process ar(1) archive using libarchive. */ + if (ac_detect_ar(ifd)) { + ac_create_ar(ecp, ifd, ofd); + goto copy_done; + } +#endif + + if (lseek(ifd, 0, SEEK_SET) < 0) + err(EXIT_FAILURE, "lseek failed"); + + /* + * If input object is not ELF file, convert it to an intermediate + * ELF object before processing. + */ + if (ecp->itf != ETF_ELF) { + create_tempfile(&elftemp, &efd); + if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); + if (ecp->itf == ETF_BINARY) + create_elf_from_binary(ecp, ifd, src); + else if (ecp->itf == ETF_IHEX) + create_elf_from_ihex(ecp, ifd); + else if (ecp->itf == ETF_SREC) + create_elf_from_srec(ecp, ifd); + else + errx(EXIT_FAILURE, "Internal: invalid target flavour"); + elf_end(ecp->eout); + + /* Open intermediate ELF object as new input object. */ + close(ifd); + if ((ifd = open(elftemp, O_RDONLY)) == -1) + err(EXIT_FAILURE, "open %s failed", src); + close(efd); + free(elftemp); + } + + if ((ecp->ein = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + switch (elf_kind(ecp->ein)) { + case ELF_K_NONE: + errx(EXIT_FAILURE, "file format not recognized"); + case ELF_K_ELF: + if ((ecp->eout = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_begin() failed: %s", + elf_errmsg(-1)); + + /* elfcopy(1) manage ELF layout by itself. */ + elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); + + /* + * Create output ELF object. + */ + create_elf(ecp); + elf_end(ecp->eout); + + /* + * Convert the output ELF object to binary/srec/ihex if need. + */ + if (ecp->otf != ETF_ELF) { + /* + * Create (another) tempfile for binary/srec/ihex + * output object. + */ + if (tempfile != NULL) { + if (unlink(tempfile) < 0) + err(EXIT_FAILURE, "unlink %s failed", + tempfile); + free(tempfile); + } + create_tempfile(&tempfile, &ofd0); + + + /* + * Rewind the file descriptor being processed. + */ + if (lseek(ofd, 0, SEEK_SET) < 0) + err(EXIT_FAILURE, + "lseek failed for the output object"); + + /* + * Call flavour-specific conversion routine. + */ + switch (ecp->otf) { + case ETF_BINARY: + create_binary(ofd, ofd0); + break; + case ETF_IHEX: + create_ihex(ofd, ofd0); + break; + case ETF_SREC: + create_srec(ecp, ofd, ofd0, + dst != NULL ? dst : src); + break; + default: + errx(EXIT_FAILURE, "Internal: unsupported" + " output flavour %d", ecp->oec); + } + + close(ofd); + ofd = ofd0; + } + + break; + + case ELF_K_AR: + /* XXX: Not yet supported. */ + break; + default: + errx(EXIT_FAILURE, "file format not supported"); + } + + elf_end(ecp->ein); + +#ifndef LIBELF_AR +copy_done: +#endif + + if (tempfile != NULL) { + if (dst == NULL) + dst = src; + + if (copy_from_tempfile(tempfile, dst, ofd, &tfd) < 0) + err(EXIT_FAILURE, "creation of %s failed", dst); + + free(tempfile); + tempfile = NULL; + + ofd = tfd; + } + + if (strcmp(dst, "/dev/null") && fchmod(ofd, sb.st_mode) == -1) + err(EXIT_FAILURE, "fchmod %s failed", dst); + + if ((ecp->flags & PRESERVE_DATE) && + elftc_set_timestamps(dst, &sb) < 0) + err(EXIT_FAILURE, "setting timestamps failed"); + + close(ifd); + close(ofd); +} + +static void +elfcopy_main(struct elfcopy *ecp, int argc, char **argv) +{ + struct sec_action *sac; + const char *infile, *outfile; + char *fn, *s; + int opt; + + while ((opt = getopt_long(argc, argv, "dB:gG:I:j:K:L:N:O:pR:s:SwW:xXV", + elfcopy_longopts, NULL)) != -1) { + switch(opt) { + case 'B': + /* ignored */ + break; + case 'R': + sac = lookup_sec_act(ecp, optarg, 1); + if (sac->copy != 0) + errx(EXIT_FAILURE, + "both copy and remove specified"); + sac->remove = 1; + ecp->flags |= SEC_REMOVE; + break; + case 'S': + ecp->strip = STRIP_ALL; + break; + case 'g': + ecp->strip = STRIP_DEBUG; + break; + case 'G': + ecp->flags |= KEEP_GLOBAL; + add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEPG); + break; + case 'I': + case 's': + set_input_target(ecp, optarg); + break; + case 'j': + sac = lookup_sec_act(ecp, optarg, 1); + if (sac->remove != 0) + errx(EXIT_FAILURE, + "both copy and remove specified"); + sac->copy = 1; + ecp->flags |= SEC_COPY; + break; + case 'K': + add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP); + break; + case 'L': + add_to_symop_list(ecp, optarg, NULL, SYMOP_LOCALIZE); + break; + case 'N': + add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP); + break; + case 'O': + set_output_target(ecp, optarg); + break; + case 'p': + ecp->flags |= PRESERVE_DATE; + break; + case 'V': + print_version(); + break; + case 'w': + ecp->flags |= WILDCARD; + break; + case 'W': + add_to_symop_list(ecp, optarg, NULL, SYMOP_WEAKEN); + break; + case 'x': + ecp->flags |= DISCARD_LOCAL; + break; + case 'X': + ecp->flags |= DISCARD_LLABEL; + break; + case ECP_ADD_GNU_DEBUGLINK: + ecp->debuglink = optarg; + break; + case ECP_ADD_SECTION: + add_section(ecp, optarg); + break; + case ECP_CHANGE_ADDR: + ecp->change_addr = (int64_t) strtoll(optarg, NULL, 0); + break; + case ECP_CHANGE_SEC_ADDR: + parse_sec_address_op(ecp, opt, "--change-section-addr", + optarg); + break; + case ECP_CHANGE_SEC_LMA: + parse_sec_address_op(ecp, opt, "--change-section-lma", + optarg); + break; + case ECP_CHANGE_SEC_VMA: + parse_sec_address_op(ecp, opt, "--change-section-vma", + optarg); + break; + case ECP_CHANGE_START: + ecp->change_start = (int64_t) strtoll(optarg, NULL, 0); + break; + case ECP_CHANGE_WARN: + /* default */ + break; + case ECP_GAP_FILL: + ecp->fill = (uint8_t) strtoul(optarg, NULL, 0); + ecp->flags |= GAP_FILL; + break; + case ECP_GLOBALIZE_SYMBOL: + add_to_symop_list(ecp, optarg, NULL, SYMOP_GLOBALIZE); + break; + case ECP_GLOBALIZE_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_GLOBALIZE); + break; + case ECP_KEEP_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_KEEP); + break; + case ECP_KEEP_GLOBAL_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_KEEPG); + break; + case ECP_LOCALIZE_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_LOCALIZE); + break; + case ECP_NO_CHANGE_WARN: + ecp->flags |= NO_CHANGE_WARN; + break; + case ECP_ONLY_DEBUG: + ecp->strip = STRIP_NONDEBUG; + break; + case ECP_PAD_TO: + ecp->pad_to = (uint64_t) strtoull(optarg, NULL, 0); + break; + case ECP_PREFIX_ALLOC: + ecp->prefix_alloc = optarg; + break; + case ECP_PREFIX_SEC: + ecp->prefix_sec = optarg; + break; + case ECP_PREFIX_SYM: + ecp->prefix_sym = optarg; + break; + case ECP_REDEF_SYMBOL: + if ((s = strchr(optarg, '=')) == NULL) + errx(EXIT_FAILURE, + "illegal format for --redefine-sym"); + *s++ = '\0'; + add_to_symop_list(ecp, optarg, s, SYMOP_REDEF); + break; + case ECP_REDEF_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_REDEF); + break; + case ECP_RENAME_SECTION: + if ((fn = strchr(optarg, '=')) == NULL) + errx(EXIT_FAILURE, + "illegal format for --rename-section"); + *fn++ = '\0'; + + /* Check for optional flags. */ + if ((s = strchr(fn, ',')) != NULL) + *s++ = '\0'; + + sac = lookup_sec_act(ecp, optarg, 1); + sac->rename = 1; + sac->newname = fn; + if (s != NULL) + parse_sec_flags(sac, s); + break; + case ECP_SET_OSABI: + set_osabi(ecp, optarg); + break; + case ECP_SET_SEC_FLAGS: + if ((s = strchr(optarg, '=')) == NULL) + errx(EXIT_FAILURE, + "illegal format for --set-section-flags"); + *s++ = '\0'; + sac = lookup_sec_act(ecp, optarg, 1); + parse_sec_flags(sac, s); + break; + case ECP_SET_START: + ecp->flags |= SET_START; + ecp->set_start = (uint64_t) strtoull(optarg, NULL, 0); + break; + case ECP_SREC_FORCE_S3: + ecp->flags |= SREC_FORCE_S3; + break; + case ECP_SREC_LEN: + ecp->flags |= SREC_FORCE_LEN; + ecp->srec_len = strtoul(optarg, NULL, 0); + break; + case ECP_STRIP_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_STRIP); + break; + case ECP_STRIP_UNNEEDED: + ecp->strip = STRIP_UNNEEDED; + break; + case ECP_WEAKEN_ALL: + ecp->flags |= WEAKEN_ALL; + break; + case ECP_WEAKEN_SYMBOLS: + parse_symlist_file(ecp, optarg, SYMOP_WEAKEN); + break; + default: + elfcopy_usage(); + } + } + + if (optind == argc || optind + 2 < argc) + elfcopy_usage(); + + infile = argv[optind]; + outfile = NULL; + if (optind + 1 < argc) + outfile = argv[optind + 1]; + + create_file(ecp, infile, outfile); +} + +static void +mcs_main(struct elfcopy *ecp, int argc, char **argv) +{ + struct sec_action *sac; + const char *string; + int append, delete, compress, name, print; + int opt, i; + + append = delete = compress = name = print = 0; + string = NULL; + while ((opt = getopt_long(argc, argv, "a:cdhn:pV", mcs_longopts, + NULL)) != -1) { + switch(opt) { + case 'a': + append = 1; + string = optarg; /* XXX multiple -a not supported */ + break; + case 'c': + compress = 1; + break; + case 'd': + delete = 1; + break; + case 'n': + name = 1; + (void)lookup_sec_act(ecp, optarg, 1); + break; + case 'p': + print = 1; + break; + case 'V': + print_version(); + break; + case 'h': + default: + mcs_usage(); + } + } + + if (optind == argc) + mcs_usage(); + + /* Must specify one operation at least. */ + if (!append && !compress && !delete && !print) + mcs_usage(); + + /* + * If we are going to delete, ignore other operations. This is + * different from the Solaris implementation, which can print + * and delete a section at the same time, for example. Also, this + * implementation do not respect the order between operations that + * user specified, i.e., "mcs -pc a.out" equals to "mcs -cp a.out". + */ + if (delete) { + append = compress = print = 0; + ecp->flags |= SEC_REMOVE; + } + if (append) + ecp->flags |= SEC_APPEND; + if (compress) + ecp->flags |= SEC_COMPRESS; + if (print) + ecp->flags |= SEC_PRINT; + + /* .comment is the default section to operate on. */ + if (!name) + (void)lookup_sec_act(ecp, ".comment", 1); + + STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { + sac->append = append; + sac->compress = compress; + sac->print = print; + sac->remove = delete; + sac->string = string; + } + + for (i = optind; i < argc; i++) { + /* If only -p is specified, output to /dev/null */ + if (print && !append && !compress && !delete) + create_file(ecp, argv[i], "/dev/null"); + else + create_file(ecp, argv[i], NULL); + } +} + +static void +strip_main(struct elfcopy *ecp, int argc, char **argv) +{ + struct sec_action *sac; + const char *outfile; + int opt; + int i; + + outfile = NULL; + while ((opt = getopt_long(argc, argv, "hI:K:N:o:O:pR:sSdgVxXw", + strip_longopts, NULL)) != -1) { + switch(opt) { + case 'R': + sac = lookup_sec_act(ecp, optarg, 1); + sac->remove = 1; + ecp->flags |= SEC_REMOVE; + break; + case 's': + ecp->strip = STRIP_ALL; + break; + case 'S': + case 'g': + case 'd': + ecp->strip = STRIP_DEBUG; + break; + case 'I': + /* ignored */ + break; + case 'K': + add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP); + break; + case 'N': + add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP); + break; + case 'o': + outfile = optarg; + break; + case 'O': + set_output_target(ecp, optarg); + break; + case 'p': + ecp->flags |= PRESERVE_DATE; + break; + case 'V': + print_version(); + break; + case 'w': + ecp->flags |= WILDCARD; + break; + case 'x': + ecp->flags |= DISCARD_LOCAL; + break; + case 'X': + ecp->flags |= DISCARD_LLABEL; + break; + case ECP_ONLY_DEBUG: + ecp->strip = STRIP_NONDEBUG; + break; + case ECP_STRIP_UNNEEDED: + ecp->strip = STRIP_UNNEEDED; + break; + case 'h': + default: + strip_usage(); + } + } + + if (ecp->strip == 0 && + ((ecp->flags & DISCARD_LOCAL) == 0) && + ((ecp->flags & DISCARD_LLABEL) == 0)) + ecp->strip = STRIP_ALL; + if (optind == argc) + strip_usage(); + + for (i = optind; i < argc; i++) + create_file(ecp, argv[i], outfile); +} + +static void +parse_sec_flags(struct sec_action *sac, char *s) +{ + const char *flag; + int found, i; + + for (flag = strtok(s, ","); flag; flag = strtok(NULL, ",")) { + found = 0; + for (i = 0; sec_flags[i].name != NULL; i++) + if (strcasecmp(sec_flags[i].name, flag) == 0) { + sac->flags |= sec_flags[i].value; + found = 1; + break; + } + if (!found) + errx(EXIT_FAILURE, "unrecognized section flag %s", + flag); + } +} + +static void +parse_sec_address_op(struct elfcopy *ecp, int optnum, const char *optname, + char *s) +{ + struct sec_action *sac; + const char *name; + char *v; + char op; + + name = v = s; + do { + v++; + } while (*v != '\0' && *v != '=' && *v != '+' && *v != '-'); + if (*v == '\0' || *(v + 1) == '\0') + errx(EXIT_FAILURE, "invalid format for %s", optname); + op = *v; + *v++ = '\0'; + sac = lookup_sec_act(ecp, name, 1); + switch (op) { + case '=': + if (optnum == ECP_CHANGE_SEC_LMA || + optnum == ECP_CHANGE_SEC_ADDR) { + sac->setlma = 1; + sac->lma = (uint64_t) strtoull(v, NULL, 0); + } + if (optnum == ECP_CHANGE_SEC_VMA || + optnum == ECP_CHANGE_SEC_ADDR) { + sac->setvma = 1; + sac->vma = (uint64_t) strtoull(v, NULL, 0); + } + break; + case '+': + if (optnum == ECP_CHANGE_SEC_LMA || + optnum == ECP_CHANGE_SEC_ADDR) + sac->lma_adjust = (int64_t) strtoll(v, NULL, 0); + if (optnum == ECP_CHANGE_SEC_VMA || + optnum == ECP_CHANGE_SEC_ADDR) + sac->vma_adjust = (int64_t) strtoll(v, NULL, 0); + break; + case '-': + if (optnum == ECP_CHANGE_SEC_LMA || + optnum == ECP_CHANGE_SEC_ADDR) + sac->lma_adjust = (int64_t) -strtoll(v, NULL, 0); + if (optnum == ECP_CHANGE_SEC_VMA || + optnum == ECP_CHANGE_SEC_ADDR) + sac->vma_adjust = (int64_t) -strtoll(v, NULL, 0); + break; + default: + break; + } +} + +static void +parse_symlist_file(struct elfcopy *ecp, const char *fn, unsigned int op) +{ + struct symfile *sf; + struct stat sb; + FILE *fp; + char *data, *p, *line, *end, *e, *n; + + if (stat(fn, &sb) == -1) + err(EXIT_FAILURE, "stat %s failed", fn); + + /* Check if we already read and processed this file. */ + STAILQ_FOREACH(sf, &ecp->v_symfile, symfile_list) { + if (sf->dev == sb.st_dev && sf->ino == sb.st_ino) + goto process_symfile; + } + + if ((fp = fopen(fn, "r")) == NULL) + err(EXIT_FAILURE, "can not open %s", fn); + if ((data = malloc(sb.st_size + 1)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if (fread(data, 1, sb.st_size, fp) == 0 || ferror(fp)) + err(EXIT_FAILURE, "fread failed"); + fclose(fp); + data[sb.st_size] = '\0'; + + if ((sf = calloc(1, sizeof(*sf))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + sf->dev = sb.st_dev; + sf->ino = sb.st_ino; + sf->size = sb.st_size + 1; + sf->data = data; + +process_symfile: + + /* + * Basically what we do here is to convert EOL to '\0', and remove + * leading and trailing whitespaces for each line. + */ + + end = sf->data + sf->size; + line = NULL; + for(p = sf->data; p < end; p++) { + if ((*p == '\t' || *p == ' ') && line == NULL) + continue; + if (*p == '\r' || *p == '\n' || *p == '\0') { + *p = '\0'; + if (line == NULL) + continue; + + /* Skip comment. */ + if (*line == '#') { + line = NULL; + continue; + } + + e = p - 1; + while(e != line && (*e == '\t' || *e == ' ')) + *e-- = '\0'; + if (op != SYMOP_REDEF) + add_to_symop_list(ecp, line, NULL, op); + else { + if (strlen(line) < 3) + errx(EXIT_FAILURE, + "illegal format for" + " --redefine-sym"); + for(n = line + 1; n < e; n++) { + if (*n == ' ' || *n == '\t') { + while(*n == ' ' || *n == '\t') + *n++ = '\0'; + break; + } + } + if (n >= e) + errx(EXIT_FAILURE, + "illegal format for" + " --redefine-sym"); + add_to_symop_list(ecp, line, n, op); + } + line = NULL; + continue; + } + + if (line == NULL) + line = p; + } +} + +static void +set_input_target(struct elfcopy *ecp, const char *target_name) +{ + Elftc_Bfd_Target *tgt; + + if ((tgt = elftc_bfd_find_target(target_name)) == NULL) + errx(EXIT_FAILURE, "%s: invalid target name", target_name); + ecp->itf = elftc_bfd_target_flavor(tgt); +} + +static void +set_output_target(struct elfcopy *ecp, const char *target_name) +{ + Elftc_Bfd_Target *tgt; + + if ((tgt = elftc_bfd_find_target(target_name)) == NULL) + errx(EXIT_FAILURE, "%s: invalid target name", target_name); + ecp->otf = elftc_bfd_target_flavor(tgt); + if (ecp->otf == ETF_ELF) { + ecp->oec = elftc_bfd_target_class(tgt); + ecp->oed = elftc_bfd_target_byteorder(tgt); + ecp->oem = elftc_bfd_target_machine(tgt); + } + ecp->otgt = target_name; +} + +static void +set_osabi(struct elfcopy *ecp, const char *abi) +{ + int i, found; + + found = 0; + for (i = 0; osabis[i].name != NULL; i++) + if (strcasecmp(osabis[i].name, abi) == 0) { + ecp->abi = osabis[i].abi; + found = 1; + break; + } + if (!found) + errx(EXIT_FAILURE, "unrecognized OSABI %s", abi); +} + +#define ELFCOPY_USAGE_MESSAGE "\ +Usage: %s [options] infile [outfile]\n\ + Transform an ELF object.\n\n\ + Options:\n\ + -d | -g | --strip-debug Remove debugging information from the output.\n\ + -j SECTION | --only-section=SECTION\n\ + Copy only the named section to the output.\n\ + -p | --preserve-dates Preserve access and modification times.\n\ + -w | --wildcard Use shell-style patterns to name symbols.\n\ + -x | --discard-all Do not copy non-globals to the output.\n\ + -I FORMAT | --input-target=FORMAT\n\ + (Accepted but ignored).\n\ + -K SYM | --keep-symbol=SYM Copy symbol SYM to the output.\n\ + -L SYM | --localize-symbol=SYM\n\ + Make symbol SYM local to the output file.\n\ + -N SYM | --strip-symbol=SYM Do not copy symbol SYM to the output.\n\ + -R NAME | --remove-section=NAME\n\ + Remove the named section.\n\ + -S | --strip-all Remove all symbol and relocation information\n\ + from the output.\n\ + -V | --version Print a version identifier and exit.\n\ + -W SYM | --weaken-symbol=SYM Mark symbol SYM as weak in the output.\n\ + -X | --discard-locals Do not copy compiler generated symbols to\n\ + the output.\n\ + --add-section NAME=FILE Add the contents of FILE to the ELF object as\n\ + a new section named NAME.\n\ + --adjust-section-vma SECTION{=,+,-}VAL | \\\n\ + --change-section-address SECTION{=,+,-}VAL\n\ + Set or adjust the VMA and the LMA of the\n\ + named section by VAL.\n\ + --adjust-start=INCR | --change-start=INCR\n\ + Add INCR to the start address for the ELF\n\ + object.\n\ + --adjust-vma=INCR | --change-addresses=INCR\n\ + Increase the VMA and LMA of all sections by\n\ + INCR.\n\ + --adjust-warning | --change-warnings\n\ + Issue warnings for non-existent sections.\n\ + --change-section-lma SECTION{=,+,-}VAL\n\ + Set or adjust the LMA address of the named\n\ + section by VAL.\n\ + --change-section-vma SECTION{=,+,-}VAL\n\ + Set or adjust the VMA address of the named\n\ + section by VAL.\n\ + --gap-fill=VAL Fill the gaps between sections with bytes\n\ + of value VAL.\n\ + --no-adjust-warning| --no-change-warnings\n\ + Do not issue warnings for non-existent\n\ + sections.\n\ + --only-keep-debug Copy only debugging information.\n\ + --output-target=FORMAT Use the specified format for the output.\n\ + --pad-to=ADDRESS Pad the output object upto the given address.\n\ + --prefix-alloc-sections=STRING\n\ + Prefix the section names of all the allocated\n\ + sections with STRING.\n\ + --prefix-sections=STRING Prefix the section names of all the sections\n\ + with STRING.\n\ + --prefix-symbols=STRING Prefix the symbol names of all the symbols\n\ + with STRING.\n\ + --rename-section OLDNAME=NEWNAME[,FLAGS]\n\ + Rename and optionally change section flags.\n\ + --set-section-flags SECTION=FLAGS\n\ + Set section flags for the named section.\n\ + Supported flags are: 'alloc', 'code',\n\ + 'contents', 'data', 'debug', 'load',\n\ + 'noload', 'readonly', 'rom', and 'shared'.\n\ + --set-start=ADDRESS Set the start address of the ELF object.\n\ + --srec-forceS3 Only generate S3 S-Records.\n\ + --srec-len=LEN Set the maximum length of a S-Record line.\n\ + --strip-unneeded Do not copy relocation information.\n" + +static void +elfcopy_usage(void) +{ + (void) fprintf(stderr, ELFCOPY_USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +#define MCS_USAGE_MESSAGE "\ +Usage: %s [options] file...\n\ + Manipulate the comment section in an ELF object.\n\n\ + Options:\n\ + -a STRING Append 'STRING' to the comment section.\n\ + -c Remove duplicate entries from the comment section.\n\ + -d Delete the comment section.\n\ + -h | --help Print a help message and exit.\n\ + -n NAME Operate on the ELF section with name 'NAME'.\n\ + -p Print the contents of the comment section.\n\ + -V | --version Print a version identifier and exit.\n" + +static void +mcs_usage(void) +{ + (void) fprintf(stderr, MCS_USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +#define STRIP_USAGE_MESSAGE "\ +Usage: %s [options] file...\n\ + Discard information from ELF objects.\n\n\ + Options:\n\ + -d | -g | -S | --strip-debug Remove debugging symbols.\n\ + -h | --help Print a help message.\n\ + --only-keep-debug Keep debugging information only.\n\ + -p | --preserve-dates Preserve access and modification times.\n\ + -s | --strip-all Remove all symbols.\n\ + --strip-unneeded Remove symbols not needed for relocation\n\ + processing.\n\ + -w | --wildcard Use shell-style patterns to name symbols.\n\ + -x | --discard-all Discard all non-global symbols.\n\ + -I TGT| --input-target=TGT (Accepted, but ignored).\n\ + -K SYM | --keep-symbol=SYM Keep symbol 'SYM' in the output.\n\ + -N SYM | --strip-symbol=SYM Remove symbol 'SYM' from the output.\n\ + -O TGT | --output-target=TGT Set the output file format to 'TGT'.\n\ + -R SEC | --remove-section=SEC Remove the section named 'SEC'.\n\ + -V | --version Print a version identifier and exit.\n\ + -X | --discard-locals Remove compiler-generated local symbols.\n" + +static void +strip_usage(void) +{ + (void) fprintf(stderr, STRIP_USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +static void +print_version(void) +{ + (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); + exit(EXIT_SUCCESS); +} + +int +main(int argc, char **argv) +{ + struct elfcopy *ecp; + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "ELF library initialization failed: %s", + elf_errmsg(-1)); + + ecp = calloc(1, sizeof(*ecp)); + if (ecp == NULL) + err(EXIT_FAILURE, "calloc failed"); + memset(ecp, 0, sizeof(*ecp)); + + ecp->itf = ecp->otf = ETF_ELF; + ecp->iec = ecp->oec = ELFCLASSNONE; + ecp->oed = ELFDATANONE; + ecp->abi = -1; + /* There is always an empty section. */ + ecp->nos = 1; + ecp->fill = 0; + + STAILQ_INIT(&ecp->v_seg); + STAILQ_INIT(&ecp->v_sac); + STAILQ_INIT(&ecp->v_sadd); + STAILQ_INIT(&ecp->v_symop); + STAILQ_INIT(&ecp->v_symfile); + STAILQ_INIT(&ecp->v_arobj); + TAILQ_INIT(&ecp->v_sec); + + if ((ecp->progname = ELFTC_GETPROGNAME()) == NULL) + ecp->progname = "elfcopy"; + + if (strcmp(ecp->progname, "strip") == 0) + strip_main(ecp, argc, argv); + else if (strcmp(ecp->progname, "mcs") == 0) + mcs_main(ecp, argc, argv); + else + elfcopy_main(ecp, argc, argv); + + free_sec_add(ecp); + free_sec_act(ecp); + free(ecp); + + exit(EXIT_SUCCESS); +} diff --git a/contrib/elftoolchain/elfcopy/mcs.1 b/contrib/elftoolchain/elfcopy/mcs.1 new file mode 100644 index 000000000000..edbafb7b88a7 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/mcs.1 @@ -0,0 +1,125 @@ +.\" Copyright (c) 2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: mcs.1 2247 2011-11-29 08:41:34Z jkoshy $ +.\" +.Dd November 29, 2011 +.Os +.Dt MCS 1 +.Sh NAME +.Nm mcs +.Nd manipulate the comment section of an ELF object +.Sh SYNOPSIS +.Nm +.Op Fl a Ar string +.Op Fl c +.Op Fl n Ar name +.Op Fl p +.Ar +.Nm +.Fl d +.Op Fl n Ar name +.Ar +.Nm +.Fl h | Fl -help +.Nm +.Fl V | Fl -version +.Sh DESCRIPTION +The +.Nm +utility is used to manipulate comment sections in an ELF object. +If a command-line argument +.Ar file +names an +.Xr ar 1 +archive, then +.Nm +will operate on the ELF objects contained in the archive. +.Pp +By default +.Nm +operates on the ELF section named +.Dq .comment . +This may be changed using the +.Fl n +option. +.Pp +The +.Nm +utility supports the following options: +.Bl -tag -width ".Fl a Ar string" +.It Fl a Ar string +Append the text in +.Ar string +to the comment section. +This option may be specified multiple times. +.It Fl c +Compress the comment section by removing duplicate entries. +.It Fl d +Delete the comment section from the ELF object. +.It Fl h | Fl -help +Display a usage message and exit. +.It Fl n Ar name +Operate on the section named +.Ar name . +.It Fl p +Print the contents of the comment section. +This step is taken after actions specified by the +.Fl a +and +.Fl c +options (if any) are completed. +.It Fl V | Fl -version +Print a version identifier and exit. +.El +.Sh COMPATIBILITY +The behavior of the +.Nm +utility differs from its SVR4 counterpart in the following ways: +.Bl -bullet -compact +.It +If the +.Fl d +option is specified, it causes any +.Fl a , +.Fl c +and +.Fl p +options present to be ignored. +.It +The order of options +.Fl a , +.Fl c , +.Fl d , +and +.Fl p +on the command line is not significant. +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr ar 1 , +.Xr elfcopy 1 , +.Xr ld 1 , +.Xr nm 1 , +.Xr strip 1 diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c new file mode 100644 index 000000000000..d01659a935ee --- /dev/null +++ b/contrib/elftoolchain/elfcopy/sections.c @@ -0,0 +1,1518 @@ +/*- + * Copyright (c) 2007-2011 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: sections.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); + +static void add_gnu_debuglink(struct elfcopy *ecp); +static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); +static void check_section_rename(struct elfcopy *ecp, struct section *s); +static void filter_reloc(struct elfcopy *ecp, struct section *s); +static int get_section_flags(struct elfcopy *ecp, const char *name); +static void insert_sections(struct elfcopy *ecp); +static void insert_to_strtab(struct section *t, const char *s); +static int is_append_section(struct elfcopy *ecp, const char *name); +static int is_compress_section(struct elfcopy *ecp, const char *name); +static int is_debug_section(const char *name); +static int is_modify_section(struct elfcopy *ecp, const char *name); +static int is_print_section(struct elfcopy *ecp, const char *name); +static int lookup_string(struct section *t, const char *s); +static void modify_section(struct elfcopy *ecp, struct section *s); +static void pad_section(struct elfcopy *ecp, struct section *s); +static void print_data(const char *d, size_t sz); +static void print_section(struct section *s); +static void *read_section(struct section *s, size_t *size); +static void update_reloc(struct elfcopy *ecp, struct section *s); + +int +is_remove_section(struct elfcopy *ecp, const char *name) +{ + + /* Always keep section name table */ + if (strcmp(name, ".shstrtab") == 0) + return 0; + if (strcmp(name, ".symtab") == 0 || + strcmp(name, ".strtab") == 0) { + if (ecp->strip == STRIP_ALL && lookup_symop_list( + ecp, NULL, SYMOP_KEEP) == NULL) + return (1); + else + return (0); + } + + if (is_debug_section(name)) { + if (ecp->strip == STRIP_ALL || + ecp->strip == STRIP_DEBUG || + ecp->strip == STRIP_UNNEEDED || + (ecp->flags & DISCARD_LOCAL)) + return (1); + if (ecp->strip == STRIP_NONDEBUG) + return (0); + } + + if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { + struct sec_action *sac; + + sac = lookup_sec_act(ecp, name, 0); + if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) + return (1); + if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) + return (1); + } + + return (0); +} + +/* + * Relocation section needs to be removed if the section it applies to + * will be removed. + */ +int +is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) +{ + const char *name; + GElf_Shdr ish; + Elf_Scn *is; + size_t indx; + int elferr; + + if (elf_getshstrndx(ecp->ein, &indx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", + elf_errmsg(-1)); + + is = NULL; + while ((is = elf_nextscn(ecp->ein, is)) != NULL) { + if (sh_info == elf_ndxscn(is)) { + if (gelf_getshdr(is, &ish) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == + NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (is_remove_section(ecp, name)) + return (1); + else + return (0); + } + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); + + /* Remove reloc section if we can't find the target section. */ + return (1); +} + +static int +is_append_section(struct elfcopy *ecp, const char *name) +{ + struct sec_action *sac; + + sac = lookup_sec_act(ecp, name, 0); + if (sac != NULL && sac->append != 0 && sac->string != NULL) + return (1); + + return (0); +} + +static int +is_compress_section(struct elfcopy *ecp, const char *name) +{ + struct sec_action *sac; + + sac = lookup_sec_act(ecp, name, 0); + if (sac != NULL && sac->compress != 0) + return (1); + + return (0); +} + +static void +check_section_rename(struct elfcopy *ecp, struct section *s) +{ + struct sec_action *sac; + char *prefix; + size_t namelen; + + if (s->pseudo) + return; + + sac = lookup_sec_act(ecp, s->name, 0); + if (sac != NULL && sac->rename) + s->name = sac->newname; + + if (!strcmp(s->name, ".symtab") || + !strcmp(s->name, ".strtab") || + !strcmp(s->name, ".shstrtab")) + return; + + prefix = NULL; + if (s->loadable && ecp->prefix_alloc != NULL) + prefix = ecp->prefix_alloc; + else if (ecp->prefix_sec != NULL) + prefix = ecp->prefix_sec; + + if (prefix != NULL) { + namelen = strlen(s->name) + strlen(prefix) + 1; + if ((s->newname = malloc(namelen)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + snprintf(s->newname, namelen, "%s%s", prefix, s->name); + s->name = s->newname; + } +} + +static int +get_section_flags(struct elfcopy *ecp, const char *name) +{ + struct sec_action *sac; + + sac = lookup_sec_act(ecp, name, 0); + if (sac != NULL && sac->flags) + return sac->flags; + + return (0); +} + +/* + * Determine whether the section are debugging section. + * According to libbfd, debugging sections are recognized + * only by name. + */ +static int +is_debug_section(const char *name) +{ + const char *dbg_sec[] = { + ".debug", + ".gnu.linkonce.wi.", + ".line", + ".stab", + NULL + }; + const char **p; + + for(p = dbg_sec; *p; p++) { + if (strncmp(name, *p, strlen(*p)) == 0) + return (1); + } + + return (0); +} + +static int +is_print_section(struct elfcopy *ecp, const char *name) +{ + struct sec_action *sac; + + sac = lookup_sec_act(ecp, name, 0); + if (sac != NULL && sac->print != 0) + return (1); + + return (0); +} + +static int +is_modify_section(struct elfcopy *ecp, const char *name) +{ + + if (is_append_section(ecp, name) || + is_compress_section(ecp, name)) + return (1); + + return (0); +} + +struct sec_action* +lookup_sec_act(struct elfcopy *ecp, const char *name, int add) +{ + struct sec_action *sac; + + if (name == NULL) + return NULL; + + STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { + if (strcmp(name, sac->name) == 0) + return sac; + } + + if (add == 0) + return NULL; + + if ((sac = malloc(sizeof(*sac))) == NULL) + errx(EXIT_FAILURE, "not enough memory"); + memset(sac, 0, sizeof(*sac)); + sac->name = name; + STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); + + return (sac); +} + +void +free_sec_act(struct elfcopy *ecp) +{ + struct sec_action *sac, *sac_temp; + + STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { + STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); + free(sac); + } +} + +void +insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) +{ + struct section *s; + + if (!tail) { + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (sec->off < s->off) { + TAILQ_INSERT_BEFORE(s, sec, sec_list); + goto inc_nos; + } + } + } + + TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); + +inc_nos: + if (sec->pseudo == 0) + ecp->nos++; +} + +/* + * First step of section creation: create scn and internal section + * structure, discard sections to be removed. + */ +void +create_scn(struct elfcopy *ecp) +{ + struct section *s; + const char *name; + Elf_Scn *is; + GElf_Shdr ish; + size_t indx; + uint64_t oldndx, newndx; + int elferr, sec_flags; + + /* + * Insert a pseudo section that contains the ELF header + * and program header. Used as reference for section offset + * or load address adjustment. + */ + if ((s = calloc(1, sizeof(*s))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + s->off = 0; + s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + + gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); + s->align = 1; + s->pseudo = 1; + s->loadable = add_to_inseg_list(ecp, s); + insert_to_sec_list(ecp, s, 0); + + /* Create internal .shstrtab section. */ + init_shstrtab(ecp); + + if (elf_getshstrndx(ecp->ein, &indx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", + elf_errmsg(-1)); + + is = NULL; + while ((is = elf_nextscn(ecp->ein, is)) != NULL) { + if (gelf_getshdr(is, &ish) == NULL) + errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + + /* Skip sections to be removed. */ + if (is_remove_section(ecp, name)) + continue; + + /* + * Relocation section need to be remove if the section + * it applies will be removed. + */ + if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) + if (ish.sh_info != 0 && + is_remove_reloc_sec(ecp, ish.sh_info)) + continue; + + /* Get section flags set by user. */ + sec_flags = get_section_flags(ecp, name); + + /* Create internal section object. */ + if (strcmp(name, ".shstrtab") != 0) { + if ((s = calloc(1, sizeof(*s))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + s->name = name; + s->is = is; + s->off = ish.sh_offset; + s->sz = ish.sh_size; + s->align = ish.sh_addralign; + s->type = ish.sh_type; + s->vma = ish.sh_addr; + + /* + * Search program headers to determine whether section + * is loadable, but if user explicitly set section flags + * while neither "load" nor "alloc" is set, we make the + * section unloadable. + */ + if (sec_flags && + (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) + s->loadable = 0; + else + s->loadable = add_to_inseg_list(ecp, s); + } else { + /* Assuming .shstrtab is "unloadable". */ + s = ecp->shstrtab; + s->off = ish.sh_offset; + } + + oldndx = newndx = SHN_UNDEF; + if (strcmp(name, ".symtab") != 0 && + strcmp(name, ".strtab") != 0) { + if (!strcmp(name, ".shstrtab")) { + /* + * Add sections specified by --add-section and + * gnu debuglink. we want these sections have + * smaller index than .shstrtab section. + */ + if (ecp->debuglink != NULL) + add_gnu_debuglink(ecp); + if (ecp->flags & SEC_ADD) + insert_sections(ecp); + } + if ((s->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) + errx(EXIT_FAILURE, "elf_ndxscn failed: %s", + elf_errmsg(-1)); + } + if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) + errx(EXIT_FAILURE, "elf_ndxscn failed: %s", + elf_errmsg(-1)); + if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) + ecp->secndx[oldndx] = newndx; + + /* + * If strip action is STRIP_NONDEBUG(only keep debug), + * change sections flags of loadable sections to SHF_NOBITS, + * and the content of those sections will be ignored. + */ + if (ecp->strip == STRIP_NONDEBUG && (ish.sh_flags & SHF_ALLOC)) + s->type = SHT_NOBITS; + + check_section_rename(ecp, s); + + /* create section header based on input object. */ + if (strcmp(name, ".symtab") != 0 && + strcmp(name, ".strtab") != 0 && + strcmp(name, ".shstrtab") != 0) + copy_shdr(ecp, s, NULL, 0, sec_flags); + + if (strcmp(name, ".symtab") == 0) { + ecp->flags |= SYMTAB_EXIST; + ecp->symtab = s; + } + if (strcmp(name, ".strtab") == 0) + ecp->strtab = s; + + insert_to_sec_list(ecp, s, 0); + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); +} + +struct section * +insert_shtab(struct elfcopy *ecp, int tail) +{ + struct section *s, *shtab; + GElf_Ehdr ieh; + int nsecs; + + /* + * Treat section header table as a "pseudo" section, insert it + * into section list, so later it will get sorted and resynced + * just as normal sections. + */ + if ((shtab = calloc(1, sizeof(*shtab))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + if (!tail) { + /* shoff of input object is used as a hint. */ + if (gelf_getehdr(ecp->ein, &ieh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + shtab->off = ieh.e_shoff; + } else + shtab->off = 0; + /* Calculate number of sections in the output object. */ + nsecs = 0; + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (!s->pseudo) + nsecs++; + } + /* Remember there is always a null section, so we +1 here. */ + shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); + if (shtab->sz == 0) + errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); + shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); + shtab->loadable = 0; + shtab->pseudo = 1; + insert_to_sec_list(ecp, shtab, tail); + + return (shtab); +} + +void +copy_content(struct elfcopy *ecp) +{ + struct section *s; + + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + /* Skip pseudo section. */ + if (s->pseudo) + continue; + + /* Skip special sections. */ + if (strcmp(s->name, ".symtab") == 0 || + strcmp(s->name, ".strtab") == 0 || + strcmp(s->name, ".shstrtab") == 0) + continue; + + /* + * If strip action is STRIP_ALL, relocation info need + * to be stripped. Skip filtering otherwisw. + */ + if (ecp->strip == STRIP_ALL && + (s->type == SHT_REL || s->type == SHT_RELA)) + filter_reloc(ecp, s); + + if (is_modify_section(ecp, s->name)) + modify_section(ecp, s); + + copy_data(s); + + /* + * If symbol table is modified, relocation info might + * need update, as symbol index may have changed. + */ + if ((ecp->flags & SYMTAB_INTACT) == 0 && + (ecp->flags & SYMTAB_EXIST) && + (s->type == SHT_REL || s->type == SHT_RELA)) + update_reloc(ecp, s); + + if (is_print_section(ecp, s->name)) + print_section(s); + } +} + +/* + * Filter relocation entries, only keep those entries whose + * symbol is in the keep list. + */ +static void +filter_reloc(struct elfcopy *ecp, struct section *s) +{ + const char *name; + GElf_Shdr ish; + GElf_Rel rel; + GElf_Rela rela; + Elf32_Rel *rel32; + Elf64_Rel *rel64; + Elf32_Rela *rela32; + Elf64_Rela *rela64; + Elf_Data *id; + uint64_t cap, n, nrels; + int elferr, i; + + if (gelf_getshdr(s->is, &ish) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + + /* We don't want to touch relocation info for dynamic symbols. */ + if ((ecp->flags & SYMTAB_EXIST) == 0) { + if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { + /* + * This reloc section applies to the symbol table + * that was stripped, so discard whole section. + */ + s->nocopy = 1; + s->sz = 0; + } + return; + } else { + /* Symbol table exist, check if index equals. */ + if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) + return; + } + +#define COPYREL(REL, SZ) do { \ + if (nrels == 0) { \ + if ((REL##SZ = malloc(cap * \ + sizeof(Elf##SZ##_Rel))) == NULL) \ + err(EXIT_FAILURE, "malloc failed"); \ + } \ + if (nrels >= cap) { \ + cap *= 2; \ + if ((REL##SZ = realloc(REL##SZ, cap * \ + sizeof(Elf##SZ##_Rel))) == NULL) \ + err(EXIT_FAILURE, "realloc failed"); \ + } \ + REL##SZ[nrels].r_offset = REL.r_offset; \ + REL##SZ[nrels].r_info = REL.r_info; \ + if (s->type == SHT_RELA) \ + rela##SZ[nrels].r_addend = rela.r_addend; \ + nrels++; \ +} while (0) + + nrels = 0; + cap = 4; /* keep list is usually small. */ + rel32 = NULL; + rel64 = NULL; + rela32 = NULL; + rela64 = NULL; + if ((id = elf_getdata(s->is, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(-1)); + n = ish.sh_size / ish.sh_entsize; + for(i = 0; (uint64_t)i < n; i++) { + if (s->type == SHT_REL) { + if (gelf_getrel(id, i, &rel) != &rel) + errx(EXIT_FAILURE, "gelf_getrel failed: %s", + elf_errmsg(-1)); + } else { + if (gelf_getrela(id, i, &rela) != &rela) + errx(EXIT_FAILURE, "gelf_getrel failed: %s", + elf_errmsg(-1)); + } + name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), + GELF_R_SYM(rel.r_info)); + if (name == NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { + if (ecp->oec == ELFCLASS32) { + if (s->type == SHT_REL) + COPYREL(rel, 32); + else + COPYREL(rela, 32); + } else { + if (s->type == SHT_REL) + COPYREL(rel, 64); + else + COPYREL(rela, 64); + } + } + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(elferr)); + + if (ecp->oec == ELFCLASS32) { + if (s->type == SHT_REL) + s->buf = rel32; + else + s->buf = rela32; + } else { + if (s->type == SHT_REL) + s->buf = rel64; + else + s->buf = rela64; + } + s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : + ELF_T_RELA), nrels, EV_CURRENT); + s->nocopy = 1; +} + +static void +update_reloc(struct elfcopy *ecp, struct section *s) +{ + GElf_Shdr osh; + GElf_Rel rel; + GElf_Rela rela; + Elf_Data *od; + uint64_t n; + int i; + +#define UPDATEREL(REL) do { \ + if (gelf_get##REL(od, i, &REL) != &REL) \ + errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ + elf_errmsg(-1)); \ + REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ + GELF_R_TYPE(REL.r_info)); \ + if (!gelf_update_##REL(od, i, &REL)) \ + errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ + elf_errmsg(-1)); \ +} while(0) + + if (s->sz == 0) + return; + if (gelf_getshdr(s->os, &osh) == NULL) + errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", + elf_errmsg(-1)); + /* Only process .symtab reloc info. */ + if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) + return; + if ((od = elf_getdata(s->os, NULL)) == NULL) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(-1)); + n = osh.sh_size / osh.sh_entsize; + for(i = 0; (uint64_t)i < n; i++) { + if (s->type == SHT_REL) + UPDATEREL(rel); + else + UPDATEREL(rela); + } +} + +static void +pad_section(struct elfcopy *ecp, struct section *s) +{ + GElf_Shdr osh; + Elf_Data *od; + + if (s == NULL || s->pad_sz == 0) + return; + + if ((s->pad = malloc(s->pad_sz)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + memset(s->pad, ecp->fill, s->pad_sz); + + /* Create a new Elf_Data to contain the padding bytes. */ + if ((od = elf_newdata(s->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s", + elf_errmsg(-1)); + od->d_align = 1; + od->d_off = s->sz; + od->d_buf = s->pad; + od->d_type = ELF_T_BYTE; + od->d_size = s->pad_sz; + od->d_version = EV_CURRENT; + + /* Update section header. */ + if (gelf_getshdr(s->os, &osh) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + osh.sh_size = s->sz + s->pad_sz; + if (!gelf_update_shdr(s->os, &osh)) + errx(EXIT_FAILURE, "elf_update_shdr failed: %s", + elf_errmsg(-1)); +} + +void +resync_sections(struct elfcopy *ecp) +{ + struct section *s, *ps; + GElf_Shdr osh; + uint64_t off; + int first; + + ps = NULL; + first = 1; + off = 0; + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (first) { + off = s->off; + first = 0; + } + + /* Align section offset. */ + if (off <= s->off) { + if (!s->loadable) + s->off = roundup(off, s->align); + } else { + if (s->loadable) + warnx("moving loadable section," + "is this intentional?"); + s->off = roundup(off, s->align); + } + + /* Calculate next section offset. */ + off = s->off; + if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) + off += s->sz; + + if (s->pseudo) { + ps = NULL; + continue; + } + + /* Count padding bytes added through --pad-to. */ + if (s->pad_sz > 0) + off += s->pad_sz; + + /* Update section header accordingly. */ + if (gelf_getshdr(s->os, &osh) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + osh.sh_addr = s->vma; + osh.sh_offset = s->off; + osh.sh_size = s->sz; + if (!gelf_update_shdr(s->os, &osh)) + errx(EXIT_FAILURE, "elf_update_shdr failed: %s", + elf_errmsg(-1)); + + /* Add padding for previous section, if need. */ + if (ps != NULL) { + if (ps->pad_sz > 0) { + /* Apply padding added by --pad-to. */ + pad_section(ecp, ps); + } else if ((ecp->flags & GAP_FILL) && + (ps->off + ps->sz < s->off)) { + /* + * Fill the gap between sections by padding + * the section with lower address. + */ + ps->pad_sz = s->off - (ps->off + ps->sz); + pad_section(ecp, ps); + } + } + + ps = s; + } + + /* Pad the last section, if need. */ + if (ps != NULL && ps->pad_sz > 0) + pad_section(ecp, ps); +} + +static void +modify_section(struct elfcopy *ecp, struct section *s) +{ + struct sec_action *sac; + size_t srcsz, dstsz, p, len; + char *b, *c, *d, *src, *end; + int dupe; + + src = read_section(s, &srcsz); + if (src == NULL || srcsz == 0) { + /* For empty section, we proceed if we need to append. */ + if (!is_append_section(ecp, s->name)) + return; + } + + /* Allocate buffer needed for new section data. */ + dstsz = srcsz; + if (is_append_section(ecp, s->name)) { + sac = lookup_sec_act(ecp, s->name, 0); + dstsz += strlen(sac->string) + 1; + } + if ((b = malloc(dstsz)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + s->buf = b; + + /* Compress section. */ + p = 0; + if (is_compress_section(ecp, s->name)) { + end = src + srcsz; + for(c = src; c < end;) { + len = 0; + while(c + len < end && c[len] != '\0') + len++; + if (c + len == end) { + /* XXX should we warn here? */ + strncpy(&b[p], c, len); + p += len; + break; + } + dupe = 0; + for (d = b; d < b + p; ) { + if (strcmp(d, c) == 0) { + dupe = 1; + break; + } + d += strlen(d) + 1; + } + if (!dupe) { + strncpy(&b[p], c, len); + b[p + len] = '\0'; + p += len + 1; + } + c += len + 1; + } + } else { + memcpy(b, src, srcsz); + p += srcsz; + } + + /* Append section. */ + if (is_append_section(ecp, s->name)) { + sac = lookup_sec_act(ecp, s->name, 0); + len = strlen(sac->string); + strncpy(&b[p], sac->string, len); + b[p + len] = '\0'; + p += len + 1; + } + + s->sz = p; + s->nocopy = 1; +} + +static void +print_data(const char *d, size_t sz) +{ + const char *c; + + for (c = d; c < d + sz; c++) { + if (*c == '\0') + putchar('\n'); + else + putchar(*c); + } +} + +static void +print_section(struct section *s) +{ + Elf_Data *id; + int elferr; + + if (s->buf != NULL && s->sz > 0) { + print_data(s->buf, s->sz); + } else { + id = NULL; + while ((id = elf_getdata(s->is, id)) != NULL) + print_data(id->d_buf, id->d_size); + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(elferr)); + } + putchar('\n'); +} + +static void * +read_section(struct section *s, size_t *size) +{ + Elf_Data *id; + char *b; + size_t sz; + int elferr; + + sz = 0; + b = NULL; + id = NULL; + while ((id = elf_getdata(s->is, id)) != NULL) { + if (b == NULL) + b = malloc(id->d_size); + else + b = malloc(sz + id->d_size); + if (b == NULL) + err(EXIT_FAILURE, "malloc or realloc failed"); + + memcpy(&b[sz], id->d_buf, id->d_size); + sz += id->d_size; + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(elferr)); + + *size = sz; + + return (b); +} + +void +copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, + int sec_flags) +{ + GElf_Shdr ish, osh; + + if (gelf_getshdr(s->is, &ish) == NULL) + errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", + elf_errmsg(-1)); + if (gelf_getshdr(s->os, &osh) == NULL) + errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", + elf_errmsg(-1)); + + if (copy) + (void) memcpy(&osh, &ish, sizeof(ish)); + else { + osh.sh_type = s->type; + osh.sh_addr = s->vma; + osh.sh_offset = s->off; + osh.sh_size = s->sz; + osh.sh_link = ish.sh_link; + osh.sh_info = ish.sh_info; + osh.sh_addralign = s->align; + osh.sh_entsize = ish.sh_entsize; + + if (sec_flags) { + osh.sh_flags = 0; + if (sec_flags & SF_ALLOC) { + osh.sh_flags |= SHF_ALLOC; + if (!s->loadable) + warnx("set SHF_ALLOC flag for " + "unloadable section %s", + s->name); + } + if ((sec_flags & SF_READONLY) == 0) + osh.sh_flags |= SHF_WRITE; + if (sec_flags & SF_CODE) + osh.sh_flags |= SHF_EXECINSTR; + } else + osh.sh_flags = ish.sh_flags; + } + + if (name == NULL) + add_to_shstrtab(ecp, s->name); + else + add_to_shstrtab(ecp, name); + + if (!gelf_update_shdr(s->os, &osh)) + errx(EXIT_FAILURE, "elf_update_shdr failed: %s", + elf_errmsg(-1)); +} + +void +copy_data(struct section *s) +{ + Elf_Data *id, *od; + int elferr; + + if (s->nocopy && s->buf == NULL) + return; + + if ((id = elf_getdata(s->is, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata() failed: %s", + elf_errmsg(elferr)); + return; + } + + if ((od = elf_newdata(s->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s", + elf_errmsg(-1)); + + if (s->nocopy) { + /* Use s->buf as content if s->nocopy is set. */ + od->d_align = id->d_align; + od->d_off = 0; + od->d_buf = s->buf; + od->d_type = id->d_type; + od->d_size = s->sz; + od->d_version = id->d_version; + } else { + od->d_align = id->d_align; + od->d_off = id->d_off; + od->d_buf = id->d_buf; + od->d_type = id->d_type; + od->d_size = id->d_size; + od->d_version = id->d_version; + } +} + +struct section * +create_external_section(struct elfcopy *ecp, const char *name, char *newname, + void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, + uint64_t flags, uint64_t align, uint64_t vma, int loadable) +{ + struct section *s; + Elf_Scn *os; + Elf_Data *od; + GElf_Shdr osh; + + if ((os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn() failed: %s", + elf_errmsg(-1)); + if ((s = calloc(1, sizeof(*s))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + s->name = name; + s->newname = newname; /* needs to be free()'ed */ + s->off = off; + s->sz = size; + s->vma = vma; + s->align = align; + s->loadable = loadable; + s->is = NULL; + s->os = os; + s->type = stype; + s->nocopy = 1; + insert_to_sec_list(ecp, s, 1); + + if (gelf_getshdr(os, &osh) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + osh.sh_flags = flags; + osh.sh_type = s->type; + osh.sh_addr = s->vma; + osh.sh_addralign = s->align; + if (!gelf_update_shdr(os, &osh)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + add_to_shstrtab(ecp, name); + + if (buf != NULL && size != 0) { + if ((od = elf_newdata(os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s", + elf_errmsg(-1)); + od->d_align = align; + od->d_off = 0; + od->d_buf = buf; + od->d_size = size; + od->d_type = dtype; + od->d_version = EV_CURRENT; + } + + /* + * Clear SYMTAB_INTACT, as we probably need to update/add new + * STT_SECTION symbols into the symbol table. + */ + ecp->flags &= ~SYMTAB_INTACT; + + return (s); +} + +/* + * Insert sections specified by --add-section to the end of section list. + */ +static void +insert_sections(struct elfcopy *ecp) +{ + struct sec_add *sa; + struct section *s; + size_t off; + + /* Put these sections in the end of current list. */ + off = 0; + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->type != SHT_NOBITS && s->type != SHT_NULL) + off = s->off + s->sz; + else + off = s->off; + } + + STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { + + /* TODO: Add section header vma/lma, flag changes here */ + + (void) create_external_section(ecp, sa->name, NULL, sa->content, + sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); + } +} + +void +add_to_shstrtab(struct elfcopy *ecp, const char *name) +{ + struct section *s; + + s = ecp->shstrtab; + if (s->buf == NULL) { + insert_to_strtab(s, ""); + insert_to_strtab(s, ".symtab"); + insert_to_strtab(s, ".strtab"); + insert_to_strtab(s, ".shstrtab"); + } + insert_to_strtab(s, name); +} + +void +update_shdr(struct elfcopy *ecp, int update_link) +{ + struct section *s; + GElf_Shdr osh; + int elferr; + + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->pseudo) + continue; + + if (gelf_getshdr(s->os, &osh) == NULL) + errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", + elf_errmsg(-1)); + + /* Find section name in string table and set sh_name. */ + osh.sh_name = lookup_string(ecp->shstrtab, s->name); + + /* + * sh_link needs to be updated, since the index of the + * linked section might have changed. + */ + if (update_link && osh.sh_link != 0) + osh.sh_link = ecp->secndx[osh.sh_link]; + + /* + * sh_info of relocation section links to the section to which + * its relocation info applies. So it may need update as well. + */ + if ((s->type == SHT_REL || s->type == SHT_RELA) && + osh.sh_info != 0) + osh.sh_info = ecp->secndx[osh.sh_info]; + + if (!gelf_update_shdr(s->os, &osh)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); +} + +void +init_shstrtab(struct elfcopy *ecp) +{ + struct section *s; + + if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + s = ecp->shstrtab; + s->name = ".shstrtab"; + s->is = NULL; + s->sz = 0; + s->align = 1; + s->loadable = 0; + s->type = SHT_STRTAB; + s->vma = 0; +} + +void +set_shstrtab(struct elfcopy *ecp) +{ + struct section *s; + Elf_Data *data; + GElf_Shdr sh; + + s = ecp->shstrtab; + + if (gelf_getshdr(s->os, &sh) == NULL) + errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", + elf_errmsg(-1)); + sh.sh_addr = 0; + sh.sh_addralign = 1; + sh.sh_offset = s->off; + sh.sh_type = SHT_STRTAB; + sh.sh_flags = 0; + sh.sh_entsize = 0; + sh.sh_info = 0; + sh.sh_link = 0; + + if ((data = elf_newdata(s->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s", + elf_errmsg(-1)); + + /* + * If we don't have a symbol table, skip those a few bytes + * which are reserved for this in the beginning of shstrtab. + */ + if (!(ecp->flags & SYMTAB_EXIST)) { + s->sz -= sizeof(".symtab\0.strtab"); + memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), + s->sz); + } + + sh.sh_size = s->sz; + if (!gelf_update_shdr(s->os, &sh)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + + data->d_align = 1; + data->d_buf = s->buf; + data->d_size = s->sz; + data->d_off = 0; + data->d_type = ELF_T_BYTE; + data->d_version = EV_CURRENT; + + if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) + errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", + elf_errmsg(-1)); +} + +void +add_section(struct elfcopy *ecp, const char *arg) +{ + struct sec_add *sa; + struct stat sb; + const char *s, *fn; + FILE *fp; + int len; + + if ((s = strchr(arg, '=')) == NULL) + errx(EXIT_FAILURE, + "illegal format for --add-section option"); + if ((sa = malloc(sizeof(*sa))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + + len = s - arg; + if ((sa->name = malloc(len + 1)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + strncpy(sa->name, arg, len); + sa->name[len] = '\0'; + + fn = s + 1; + if (stat(fn, &sb) == -1) + err(EXIT_FAILURE, "stat failed"); + sa->size = sb.st_size; + if ((sa->content = malloc(sa->size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if ((fp = fopen(fn, "r")) == NULL) + err(EXIT_FAILURE, "can not open %s", fn); + if (fread(sa->content, 1, sa->size, fp) == 0 || + ferror(fp)) + err(EXIT_FAILURE, "fread failed"); + fclose(fp); + + STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); + ecp->flags |= SEC_ADD; +} + +void +free_sec_add(struct elfcopy *ecp) +{ + struct sec_add *sa, *sa_temp; + + STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { + STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); + free(sa->name); + free(sa->content); + free(sa); + } +} + +static void +add_gnu_debuglink(struct elfcopy *ecp) +{ + struct sec_add *sa; + struct stat sb; + FILE *fp; + char *fnbase, *buf; + int crc_off; + int crc; + + if (ecp->debuglink == NULL) + return; + + /* Read debug file content. */ + if ((sa = malloc(sizeof(*sa))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if ((sa->name = strdup(".gnu_debuglink")) == NULL) + err(EXIT_FAILURE, "strdup failed"); + if (stat(ecp->debuglink, &sb) == -1) + err(EXIT_FAILURE, "stat failed"); + if ((buf = malloc(sb.st_size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + if ((fp = fopen(ecp->debuglink, "r")) == NULL) + err(EXIT_FAILURE, "can not open %s", ecp->debuglink); + if (fread(buf, 1, sb.st_size, fp) == 0 || + ferror(fp)) + err(EXIT_FAILURE, "fread failed"); + fclose(fp); + + /* Calculate crc checksum. */ + crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); + free(buf); + + /* Calculate section size and the offset to store crc checksum. */ + if ((fnbase = basename(ecp->debuglink)) == NULL) + err(EXIT_FAILURE, "basename failed"); + crc_off = roundup(strlen(fnbase) + 1, 4); + sa->size = crc_off + 4; + + /* Section content. */ + if ((sa->content = calloc(1, sa->size)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + strncpy(sa->content, fnbase, strlen(fnbase)); + if (ecp->oed == ELFDATA2LSB) { + sa->content[crc_off] = crc & 0xFF; + sa->content[crc_off + 1] = (crc >> 8) & 0xFF; + sa->content[crc_off + 2] = (crc >> 16) & 0xFF; + sa->content[crc_off + 3] = crc >> 24; + } else { + sa->content[crc_off] = crc >> 24; + sa->content[crc_off + 1] = (crc >> 16) & 0xFF; + sa->content[crc_off + 2] = (crc >> 8) & 0xFF; + sa->content[crc_off + 3] = crc & 0xFF; + } + + STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); + ecp->flags |= SEC_ADD; +} + +static void +insert_to_strtab(struct section *t, const char *s) +{ + const char *r; + char *b, *c; + size_t len, slen; + int append; + + if (t->sz == 0) { + t->cap = 512; + if ((t->buf = malloc(t->cap)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + } + + slen = strlen(s); + append = 0; + b = t->buf; + for (c = b; c < b + t->sz;) { + len = strlen(c); + if (!append && len >= slen) { + r = c + (len - slen); + if (strcmp(r, s) == 0) + return; + } else if (len < slen && len != 0) { + r = s + (slen - len); + if (strcmp(c, r) == 0) { + t->sz -= len + 1; + memmove(c, c + len + 1, t->sz - (c - b)); + append = 1; + continue; + } + } + c += len + 1; + } + + while (t->sz + slen + 1 >= t->cap) { + t->cap *= 2; + if ((t->buf = realloc(t->buf, t->cap)) == NULL) + err(EXIT_FAILURE, "realloc failed"); + } + b = t->buf; + strncpy(&b[t->sz], s, slen); + b[t->sz + slen] = '\0'; + t->sz += slen + 1; +} + +static int +lookup_string(struct section *t, const char *s) +{ + const char *b, *c, *r; + size_t len, slen; + + slen = strlen(s); + b = t->buf; + for (c = b; c < b + t->sz;) { + len = strlen(c); + if (len >= slen) { + r = c + (len - slen); + if (strcmp(r, s) == 0) + return (r - b); + } + c += len + 1; + } + + return (-1); +} + +static uint32_t crctable[256] = +{ + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, + 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, + 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, + 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, + 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, + 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, + 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, + 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, + 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, + 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, + 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, + 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, + 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, + 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, + 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, + 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, + 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, + 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, + 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, + 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, + 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, + 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, + 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, + 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, + 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, + 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, + 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, + 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, + 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, + 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, + 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, + 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, + 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, + 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, + 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, + 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, + 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, + 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, + 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, + 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, + 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, + 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, + 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, + 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, + 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, + 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, + 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL +}; + +static uint32_t +calc_crc32(const char *p, size_t len, uint32_t crc) +{ + uint32_t i; + + for (i = 0; i < len; i++) { + crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); + } + + return (crc ^ 0xFFFFFFFF); +} diff --git a/contrib/elftoolchain/elfcopy/segments.c b/contrib/elftoolchain/elfcopy/segments.c new file mode 100644 index 000000000000..c54cbfcbb07a --- /dev/null +++ b/contrib/elftoolchain/elfcopy/segments.c @@ -0,0 +1,493 @@ +/*- + * Copyright (c) 2007-2010,2012 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: segments.c 2542 2012-08-12 16:14:15Z kaiwang27 $"); + +static void insert_to_inseg_list(struct segment *seg, struct section *sec); + +/* + * elfcopy's segment handling is relatively simpler and less powerful than + * libbfd. Program headers are modified or copied from input to output objects, + * but never re-generated. As a result, if the input object has incorrect + * program headers, the output object's program headers will remain incorrect + * or become even worse. + */ + +/* + * Check whether a section is "loadable". If so, add it to the + * corresponding segment list(s) and return 1. + */ +int +add_to_inseg_list(struct elfcopy *ecp, struct section *s) +{ + struct segment *seg; + int loadable; + + if (ecp->ophnum == 0) + return (0); + + /* + * Segment is a different view of an ELF object. One segment can + * contain one or more sections, and one section can be included + * in one or more segments, or not included in any segment at all. + * We call those sections which can be found in one or more segments + * "loadable" sections, and call the rest "unloadable" sections. + * We keep track of "loadable" sections in their containing + * segment(s)' v_sec queue. These information are later used to + * recalculate the extents of segments, when sections are removed, + * for example. + */ + loadable = 0; + STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { + if (s->off < seg->off) + continue; + if (s->off + s->sz > seg->off + seg->fsz && + s->type != SHT_NOBITS) + continue; + if (s->off + s->sz > seg->off + seg->msz) + continue; + + insert_to_inseg_list(seg, s); + if (seg->type == PT_LOAD) + s->seg = seg; + s->lma = seg->addr + (s->off - seg->off); + loadable = 1; + } + + return (loadable); +} + +void +adjust_addr(struct elfcopy *ecp) +{ + struct section *s, *s0; + struct segment *seg; + struct sec_action *sac; + uint64_t dl, lma, old_vma, start, end; + int found, i; + + /* + * Apply VMA and global LMA changes in the first iteration. + */ + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + + /* Only adjust loadable section's address. */ + if (!s->loadable || s->seg == NULL) + continue; + + /* Apply global LMA adjustment. */ + if (ecp->change_addr != 0) + s->lma += ecp->change_addr; + + if (!s->pseudo) { + old_vma = s->vma; + + /* Apply global VMA adjustment. */ + if (ecp->change_addr != 0) + s->vma += ecp->change_addr; + + /* Apply section VMA adjustment. */ + sac = lookup_sec_act(ecp, s->name, 0); + if (sac == NULL) + continue; + if (sac->setvma) + s->vma = sac->vma; + if (sac->vma_adjust != 0) + s->vma += sac->vma_adjust; + } + } + + /* + * Apply sections LMA change in the second iteration. + */ + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + + /* Only adjust loadable section's LMA. */ + if (!s->loadable || s->seg == NULL) + continue; + + /* + * Check if there is a LMA change request for this + * section. + */ + sac = lookup_sec_act(ecp, s->name, 0); + if (sac == NULL) + continue; + if (!sac->setlma && sac->lma_adjust == 0) + continue; + lma = s->lma; + if (sac->setlma) + lma = sac->lma; + if (sac->lma_adjust != 0) + lma += sac->lma_adjust; + if (lma == s->lma) + continue; + + /* + * Check if the LMA change is viable. + * + * 1. Check if the new LMA is properly aligned accroding to + * section alignment. + * + * 2. Compute the new extent of segment that contains this + * section, make sure it doesn't overlap with other + * segments. + */ +#ifdef DEBUG + printf("LMA for section %s: %#jx\n", s->name, lma); +#endif + + if (lma % s->align != 0) + errx(EXIT_FAILURE, "The load address %#jx for " + "section %s is not aligned to %ju", + (uintmax_t) lma, s->name, s->align); + + if (lma < s->lma) { + /* Move section to lower address. */ + if (lma < s->lma - s->seg->addr) + errx(EXIT_FAILURE, "Not enough space to move " + "section %s load address to %#jx", s->name, + (uintmax_t) lma); + start = lma - (s->lma - s->seg->addr); + if (s == s->seg->v_sec[s->seg->nsec - 1]) + end = start + s->seg->msz; + else + end = s->seg->addr + s->seg->msz; + + } else { + /* Move section to upper address. */ + if (s == s->seg->v_sec[0]) + start = lma; + else + start = s->seg->addr; + end = lma + (s->seg->addr + s->seg->msz - s->lma); + if (end < start) + errx(EXIT_FAILURE, "Not enough space to move " + "section %s load address to %#jx", s->name, + (uintmax_t) lma); + } + +#ifdef DEBUG + printf("new extent for segment containing %s: (%#jx,%#jx)\n", + s->name, start, end); +#endif + + STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { + if (seg == s->seg || seg->type != PT_LOAD) + continue; + if (start > seg->addr + seg->msz) + continue; + if (end < seg->addr) + continue; + errx(EXIT_FAILURE, "The extent of segment containing " + "section %s overlaps with segment(%#jx,%#jx)", + s->name, seg->addr, seg->addr + seg->msz); + } + + /* + * Update section LMA and file offset. + */ + + if (lma < s->lma) { + /* + * To move a section to lower load address, we decrease + * the load addresses of the section and all the + * sections that are before it, and we increase the + * file offsets of all the sections that are after it. + */ + dl = s->lma - lma; + for (i = 0; i < s->seg->nsec; i++) { + s0 = s->seg->v_sec[i]; + s0->lma -= dl; +#ifdef DEBUG + printf("section %s LMA set to %#jx\n", + s0->name, (uintmax_t) s0->lma); +#endif + if (s0 == s) + break; + } + for (i = i + 1; i < s->seg->nsec; i++) { + s0 = s->seg->v_sec[i]; + s0->off += dl; +#ifdef DEBUG + printf("section %s offset set to %#jx\n", + s0->name, (uintmax_t) s0->off); +#endif + } + } else { + /* + * To move a section to upper load address, we increase + * the load addresses of the section and all the + * sections that are after it, and we increase the + * their file offsets too unless the section in question + * is the first in its containing segment. + */ + dl = lma - s->lma; + for (i = 0; i < s->seg->nsec; i++) + if (s->seg->v_sec[i] == s) + break; + if (i >= s->seg->nsec) + errx(EXIT_FAILURE, "Internal: section `%s' not" + " found in its containing segement", + s->name); + for (; i < s->seg->nsec; i++) { + s0 = s->seg->v_sec[i]; + s0->lma += dl; +#ifdef DEBUG + printf("section %s LMA set to %#jx\n", + s0->name, (uintmax_t) s0->lma); +#endif + if (s != s->seg->v_sec[0]) { + s0->off += dl; +#ifdef DEBUG + printf("section %s offset set to %#jx\n", + s0->name, (uintmax_t) s0->off); +#endif + } + } + } + } + + /* + * Apply load address padding. + */ + + if (ecp->pad_to != 0) { + + /* + * Find the section with highest load address. + */ + + s = NULL; + STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { + if (seg->type != PT_LOAD) + continue; + for (i = seg->nsec - 1; i >= 0; i--) + if (seg->v_sec[i]->type != SHT_NOBITS) + break; + if (i < 0) + continue; + if (s == NULL) + s = seg->v_sec[i]; + else { + s0 = seg->v_sec[i]; + if (s0->lma > s->lma) + s = s0; + } + } + + if (s == NULL) + goto issue_warn; + + /* No need to pad if the pad_to address is lower. */ + if (ecp->pad_to <= s->lma + s->sz) + goto issue_warn; + + s->pad_sz = ecp->pad_to - (s->lma + s->sz); +#ifdef DEBUG + printf("pad section %s load to address %#jx by %#jx\n", s->name, + (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz); +#endif + } + +issue_warn: + + /* + * Issue a warning if there are VMA/LMA adjust requests for + * some nonexistent sections. + */ + if ((ecp->flags & NO_CHANGE_WARN) == 0) { + STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { + if (!sac->setvma && !sac->setlma && + !sac->vma_adjust && !sac->lma_adjust) + continue; + found = 0; + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->pseudo || s->name == NULL) + continue; + if (!strcmp(s->name, sac->name)) { + found = 1; + break; + } + } + if (!found) + warnx("cannot find section `%s'", sac->name); + } + } +} + +static void +insert_to_inseg_list(struct segment *seg, struct section *sec) +{ + struct section *s; + int i; + + seg->nsec++; + seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec)); + if (seg->v_sec == NULL) + err(EXIT_FAILURE, "realloc failed"); + + /* + * Sort the section in order of offset. + */ + + for (i = seg->nsec - 1; i > 0; i--) { + s = seg->v_sec[i - 1]; + if (sec->off >= s->off) { + seg->v_sec[i] = sec; + break; + } else + seg->v_sec[i] = s; + } + if (i == 0) + seg->v_sec[0] = sec; +} + +void +setup_phdr(struct elfcopy *ecp) +{ + struct segment *seg; + GElf_Phdr iphdr; + size_t iphnum; + int i; + + if (elf_getphnum(ecp->ein, &iphnum) == 0) + errx(EXIT_FAILURE, "elf_getphnum failed: %s", + elf_errmsg(-1)); + + ecp->ophnum = ecp->iphnum = iphnum; + if (iphnum == 0) + return; + + /* If --only-keep-debug is specified, discard all program headers. */ + if (ecp->strip == STRIP_NONDEBUG) { + ecp->ophnum = 0; + return; + } + + for (i = 0; (size_t)i < iphnum; i++) { + if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) + errx(EXIT_FAILURE, "gelf_getphdr failed: %s", + elf_errmsg(-1)); + if ((seg = calloc(1, sizeof(*seg))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + seg->addr = iphdr.p_vaddr; + seg->off = iphdr.p_offset; + seg->fsz = iphdr.p_filesz; + seg->msz = iphdr.p_memsz; + seg->type = iphdr.p_type; + STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list); + } +} + +void +copy_phdr(struct elfcopy *ecp) +{ + struct segment *seg; + struct section *s; + GElf_Phdr iphdr, ophdr; + int i; + + STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { + if (seg->type == PT_PHDR) { + if (!TAILQ_EMPTY(&ecp->v_sec)) { + s = TAILQ_FIRST(&ecp->v_sec); + if (s->pseudo) + seg->addr = s->lma + + gelf_fsize(ecp->eout, ELF_T_EHDR, + 1, EV_CURRENT); + } + seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR, + ecp->ophnum, EV_CURRENT); + continue; + } + + seg->fsz = seg->msz = 0; + for (i = 0; i < seg->nsec; i++) { + s = seg->v_sec[i]; + seg->msz = s->off + s->sz - seg->off; + if (s->type != SHT_NOBITS) + seg->fsz = seg->msz; + } + } + + /* + * Allocate space for program headers, note that libelf keep + * track of the number in internal variable, and a call to + * elf_update is needed to update e_phnum of ehdr. + */ + if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL) + errx(EXIT_FAILURE, "gelf_newphdr() failed: %s", + elf_errmsg(-1)); + + /* + * This elf_update() call is to update the e_phnum field in + * ehdr. It's necessary because later we will call gelf_getphdr(), + * which does sanity check by comparing ndx argument with e_phnum. + */ + if (elf_update(ecp->eout, ELF_C_NULL) < 0) + errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); + + /* + * iphnum == ophnum, since we don't remove program headers even if + * they no longer contain sections. + */ + i = 0; + STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { + if (i >= ecp->iphnum) + break; + if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) + errx(EXIT_FAILURE, "gelf_getphdr failed: %s", + elf_errmsg(-1)); + if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr) + errx(EXIT_FAILURE, "gelf_getphdr failed: %s", + elf_errmsg(-1)); + + ophdr.p_type = iphdr.p_type; + ophdr.p_vaddr = seg->addr; + ophdr.p_paddr = seg->addr; + ophdr.p_flags = iphdr.p_flags; + ophdr.p_align = iphdr.p_align; + ophdr.p_offset = seg->off; + ophdr.p_filesz = seg->fsz; + ophdr.p_memsz = seg->msz; + if (!gelf_update_phdr(ecp->eout, i, &ophdr)) + err(EXIT_FAILURE, "gelf_update_phdr failed :%s", + elf_errmsg(-1)); + + i++; + } +} diff --git a/contrib/elftoolchain/elfcopy/strip.1 b/contrib/elftoolchain/elfcopy/strip.1 new file mode 100644 index 000000000000..e07affbb9440 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/strip.1 @@ -0,0 +1,132 @@ +.\" Copyright (c) 2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOSEPH KOSHY ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JOSEPH KOSHY BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: strip.1 2069 2011-10-26 15:53:48Z jkoshy $ +.\" +.Dd September 17, 2011 +.Os +.Dt STRIP 1 +.Sh NAME +.Nm strip +.Nd discard information from ELF objects +.Sh SYNOPSIS +.Nm +.Op Fl d | Fl g | Fl S | Fl -strip-debug +.Op Fl h | Fl -help +.Op Fl -only-keep-debug +.Op Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile +.Op Fl p | Fl -preserve-dates +.Op Fl s | Fl -strip-all +.Op Fl -strip-unneeded +.Op Fl w | Fl -wildcard +.Op Fl x | Fl -discard-all +.Op Fl I Ar format | Fl -input-target= Ns Ar format +.Op Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol +.Op Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol +.Op Fl O Ar format | Fl -output-target= Ns Ar format +.Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname +.Op Fl V | Fl -version +.Op Fl X | Fl -discard-locals +.Ar +.Sh DESCRIPTION +The +.Nm +utility is used to discard information from ELF objects. +.Pp +The +.Nm +utility supports the following options: +.Bl -tag -width indent +.It Fl d | Fl g | Fl S | Fl -strip-debug +Remove debugging symbols only. +.It Fl h | Fl -help +Print a help message and exit. +.It Fl -only-keep-debug +Remove all content except that which would be used for debugging. +.It Fl o Ar outputfile | Fl -output-file= Ns Ar outputfile +Write the stripped object to file +.Ar outputfile . +The default behaviour is to modify objects in place. +.It Fl p | Fl -preserve-dates +Preserve the object's access and modification times. +.It Fl s | Fl -strip-all +Remove all symbols. +.It Fl -strip-unneeded +Remove all symbols not needed for further relocation processing. +.It Fl w | Fl -wildcard +Use shell-style patterns to name symbols. +The following meta-characters are recognized in patterns: +.Bl -tag -width "...." -compact +.It Li ! +If this is the first character of the pattern, invert the sense of the +pattern match. +.It Li * +Matches any string of characters in a symbol name. +.It Li ? +Matches zero or one character in a symbol name. +.It Li [ +Mark the start of a character class. +.It Li \e +Remove the special meaning of the next character in the pattern. +.It Li ] +Mark the end of a character class. +.El +.It Fl x | Fl -discard-all +Discard all non-global symbols. +.It Fl I Ar format | Fl -input-target= Ns Ar format +These options are accepted, but are ignored. +.It Fl K Ar symbol | Fl -keep-symbol= Ns Ar symbol +Keep the symbol +.Ar symbol +even if it would otherwise be stripped. +This option may be specified multiple times. +.It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbol +Remove the symbol +.Ar symbol +even if it would otherwise have been kept. +This option may be specified multiple times. +.It Fl O Ar format | Fl -output-target= Ns Ar format +Set the output file format to +.Ar format . +For the full list of supported formats, please see the documentation +for function +.Xr elftc_bfd_find_target 3 . +.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname +Remove the section named by the argument +.Ar sectionname . +This option may be specified multiple times. +.It Fl V | Fl -version +Print a version identifier and exit. +.It Fl X | Fl -discard-locals +Remove compiler-generated local symbols. +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr ar 1 , +.Xr elfcopy 1 , +.Xr ld 1 , +.Xr mcs 1 , +.Xr elf 3 , +.Xr elftc_bfd_find_target 3 , +.Xr fnmatch 3 diff --git a/contrib/elftoolchain/elfcopy/symbols.c b/contrib/elftoolchain/elfcopy/symbols.c new file mode 100644 index 000000000000..f2a722736c83 --- /dev/null +++ b/contrib/elftoolchain/elfcopy/symbols.c @@ -0,0 +1,1040 @@ +/*- + * Copyright (c) 2007-2013 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "elfcopy.h" + +ELFTC_VCSID("$Id: symbols.c 2971 2013-12-01 15:22:21Z kaiwang27 $"); + +/* Symbol table buffer structure. */ +struct symbuf { + Elf32_Sym *l32; /* 32bit local symbol */ + Elf32_Sym *g32; /* 32bit global symbol */ + Elf64_Sym *l64; /* 64bit local symbol */ + Elf64_Sym *g64; /* 64bit global symbol */ + size_t ngs, nls; /* number of each kind */ + size_t gcap, lcap; /* buffer capacities. */ +}; + +/* String table buffer structure. */ +struct strbuf { + char *l; /* local symbol string table */ + char *g; /* global symbol string table */ + size_t lsz, gsz; /* size of each kind */ + size_t gcap, lcap; /* buffer capacities. */ +}; + +static int is_debug_symbol(unsigned char st_info); +static int is_global_symbol(unsigned char st_info); +static int is_local_symbol(unsigned char st_info); +static int is_local_label(const char *name); +static int is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s); +static int is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, + GElf_Sym *s, const char *name); +static int is_weak_symbol(unsigned char st_info); +static int lookup_exact_string(const char *buf, size_t sz, const char *s); +static int generate_symbols(struct elfcopy *ecp); +static void mark_symbols(struct elfcopy *ecp, size_t sc); +static int match_wildcard(const char *name, const char *pattern); + +/* Convenient bit vector operation macros. */ +#define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7)) +#define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7))) +#define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7))) + +static int +is_debug_symbol(unsigned char st_info) +{ + + if (GELF_ST_TYPE(st_info) == STT_SECTION || + GELF_ST_TYPE(st_info) == STT_FILE) + return (1); + + return (0); +} + +static int +is_global_symbol(unsigned char st_info) +{ + + if (GELF_ST_BIND(st_info) == STB_GLOBAL) + return (1); + + return (0); +} + +static int +is_weak_symbol(unsigned char st_info) +{ + + if (GELF_ST_BIND(st_info) == STB_WEAK) + return (1); + + return (0); +} + +static int +is_local_symbol(unsigned char st_info) +{ + + if (GELF_ST_BIND(st_info) == STB_LOCAL) + return (1); + + return (0); +} + +static int +is_local_label(const char *name) +{ + + /* Compiler generated local symbols that start with .L */ + if (name[0] == '.' && name[1] == 'L') + return (1); + + return (0); +} + +/* + * Symbols related to relocation are needed. + */ +static int +is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s) +{ + + /* If symbol involves relocation, it is needed. */ + if (BIT_ISSET(ecp->v_rel, i)) + return (1); + + /* + * For relocatable files (.o files), global and weak symbols + * are needed. + */ + if (ecp->flags & RELOCATABLE) { + if (is_global_symbol(s->st_info) || is_weak_symbol(s->st_info)) + return (1); + } + + return (0); +} + +static int +is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, + const char *name) +{ + GElf_Sym sym0 = { + 0, /* st_name */ + 0, /* st_value */ + 0, /* st_size */ + 0, /* st_info */ + 0, /* st_other */ + SHN_UNDEF, /* st_shndx */ + }; + + if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) + return (0); + + if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) + return (1); + + /* + * Keep the first symbol if it is the special reserved symbol. + * XXX Should we generate one if it's missing? + */ + if (i == 0 && !memcmp(s, &sym0, sizeof(GElf_Sym))) + return (0); + + /* Remove the symbol if the section it refers to was removed. */ + if (s->st_shndx != SHN_UNDEF && s->st_shndx < SHN_LORESERVE && + ecp->secndx[s->st_shndx] == 0) + return (1); + + if (ecp->strip == STRIP_ALL) + return (1); + + if (ecp->v_rel == NULL) + mark_symbols(ecp, sc); + + if (is_needed_symbol(ecp, i, s)) + return (0); + + if (ecp->strip == STRIP_UNNEEDED) + return (1); + + if ((ecp->flags & DISCARD_LOCAL) && is_local_symbol(s->st_info) && + !is_debug_symbol(s->st_info)) + return (1); + + if ((ecp->flags & DISCARD_LLABEL) && is_local_symbol(s->st_info) && + !is_debug_symbol(s->st_info) && is_local_label(name)) + return (1); + + if (ecp->strip == STRIP_DEBUG && is_debug_symbol(s->st_info)) + return (1); + + return (0); +} + +/* + * Mark symbols refered by relocation entries. + */ +static void +mark_symbols(struct elfcopy *ecp, size_t sc) +{ + const char *name; + Elf_Data *d; + Elf_Scn *s; + GElf_Rel r; + GElf_Rela ra; + GElf_Shdr sh; + size_t n, indx; + int elferr, i, len; + + ecp->v_rel = calloc((sc + 7) / 8, 1); + if (ecp->v_rel == NULL) + err(EXIT_FAILURE, "calloc failed"); + + if (elf_getshstrndx(ecp->ein, &indx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", + elf_errmsg(-1)); + + s = NULL; + while ((s = elf_nextscn(ecp->ein, s)) != NULL) { + if (gelf_getshdr(s, &sh) != &sh) + errx(EXIT_FAILURE, "elf_getshdr failed: %s", + elf_errmsg(-1)); + + if (sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) + continue; + + /* + * Skip if this reloc section won't appear in the + * output object. + */ + if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (is_remove_section(ecp, name) || + is_remove_reloc_sec(ecp, sh.sh_info)) + continue; + + /* Skip if it's not for .symtab */ + if (sh.sh_link != elf_ndxscn(ecp->symtab->is)) + continue; + + d = NULL; + n = 0; + while (n < sh.sh_size && (d = elf_getdata(s, d)) != NULL) { + len = d->d_size / sh.sh_entsize; + for (i = 0; i < len; i++) { + if (sh.sh_type == SHT_REL) { + if (gelf_getrel(d, i, &r) != &r) + errx(EXIT_FAILURE, + "elf_getrel failed: %s", + elf_errmsg(-1)); + n = GELF_R_SYM(r.r_info); + } else { + if (gelf_getrela(d, i, &ra) != &ra) + errx(EXIT_FAILURE, + "elf_getrela failed: %s", + elf_errmsg(-1)); + n = GELF_R_SYM(ra.r_info); + } + if (n > 0 && n < sc) + BIT_SET(ecp->v_rel, n); + else if (n != 0) + warnx("invalid symbox index"); + } + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata failed: %s", + elf_errmsg(elferr)); + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); +} + +static int +generate_symbols(struct elfcopy *ecp) +{ + struct section *s; + struct symop *sp; + struct symbuf *sy_buf; + struct strbuf *st_buf; + const char *name; + char *newname; + unsigned char *gsym; + GElf_Shdr ish; + GElf_Sym sym; + Elf_Data* id; + Elf_Scn *is; + size_t ishstrndx, namelen, ndx, nsyms, sc, symndx; + int ec, elferr, i; + + if (elf_getshstrndx(ecp->ein, &ishstrndx) == 0) + errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", + elf_errmsg(-1)); + if ((ec = gelf_getclass(ecp->eout)) == ELFCLASSNONE) + errx(EXIT_FAILURE, "gelf_getclass failed: %s", + elf_errmsg(-1)); + + /* Create buffers for .symtab and .strtab. */ + if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + sy_buf->gcap = sy_buf->lcap = 64; + st_buf->gcap = 256; + st_buf->lcap = 64; + st_buf->lsz = 1; /* '\0' at start. */ + st_buf->gsz = 0; + nsyms = 0; + + ecp->symtab->sz = 0; + ecp->strtab->sz = 0; + ecp->symtab->buf = sy_buf; + ecp->strtab->buf = st_buf; + + /* + * Create bit vector v_secsym, which is used to mark sections + * that already have corresponding STT_SECTION symbols. + */ + ecp->v_secsym = calloc((ecp->nos + 7) / 8, 1); + if (ecp->v_secsym == NULL) + err(EXIT_FAILURE, "calloc failed"); + + /* Locate .strtab of input object. */ + symndx = 0; + name = NULL; + is = NULL; + while ((is = elf_nextscn(ecp->ein, is)) != NULL) { + if (gelf_getshdr(is, &ish) != &ish) + errx(EXIT_FAILURE, "elf_getshdr failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == + NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (strcmp(name, ".strtab") == 0) { + symndx = elf_ndxscn(is); + break; + } + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); + + /* Symbol table should exist if this function is called. */ + if (symndx == 0) { + warnx("can't find .strtab section"); + return (0); + } + + /* Locate .symtab of input object. */ + is = NULL; + while ((is = elf_nextscn(ecp->ein, is)) != NULL) { + if (gelf_getshdr(is, &ish) != &ish) + errx(EXIT_FAILURE, "elf_getshdr failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == + NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (strcmp(name, ".symtab") == 0) + break; + } + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_nextscn failed: %s", + elf_errmsg(elferr)); + if (is == NULL) + errx(EXIT_FAILURE, "can't find .strtab section"); + + /* + * Create bit vector gsym to mark global symbols, and symndx + * to keep track of symbol index changes from input object to + * output object, it is used by update_reloc() later to update + * relocation information. + */ + gsym = NULL; + sc = ish.sh_size / ish.sh_entsize; + if (sc > 0) { + ecp->symndx = calloc(sc, sizeof(*ecp->symndx)); + if (ecp->symndx == NULL) + err(EXIT_FAILURE, "calloc failed"); + gsym = calloc((sc + 7) / 8, sizeof(*gsym)); + if (gsym == NULL) + err(EXIT_FAILURE, "calloc failed"); + if ((id = elf_getdata(is, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + errx(EXIT_FAILURE, "elf_getdata failed: %s", + elf_errmsg(elferr)); + return (0); + } + } else + return (0); + + /* Copy/Filter each symbol. */ + for (i = 0; (size_t)i < sc; i++) { + if (gelf_getsym(id, i, &sym) != &sym) + errx(EXIT_FAILURE, "gelf_getsym failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, symndx, sym.st_name)) == NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + + /* Symbol filtering. */ + if (is_remove_symbol(ecp, sc, i, &sym, name) != 0) + continue; + + /* Check if we need to change the binding of this symbol. */ + if (is_global_symbol(sym.st_info) || + is_weak_symbol(sym.st_info)) { + /* + * XXX Binutils objcopy does not weaken certain + * symbols. + */ + if (ecp->flags & WEAKEN_ALL || + lookup_symop_list(ecp, name, SYMOP_WEAKEN) != NULL) + sym.st_info = GELF_ST_INFO(STB_WEAK, + GELF_ST_TYPE(sym.st_info)); + /* Do not localize undefined symbols. */ + if (sym.st_shndx != SHN_UNDEF && + lookup_symop_list(ecp, name, SYMOP_LOCALIZE) != + NULL) + sym.st_info = GELF_ST_INFO(STB_LOCAL, + GELF_ST_TYPE(sym.st_info)); + if (ecp->flags & KEEP_GLOBAL && + sym.st_shndx != SHN_UNDEF && + lookup_symop_list(ecp, name, SYMOP_KEEPG) == NULL) + sym.st_info = GELF_ST_INFO(STB_LOCAL, + GELF_ST_TYPE(sym.st_info)); + } else { + /* STB_LOCAL binding. */ + if (lookup_symop_list(ecp, name, SYMOP_GLOBALIZE) != + NULL) + sym.st_info = GELF_ST_INFO(STB_GLOBAL, + GELF_ST_TYPE(sym.st_info)); + /* XXX We should globalize weak symbol? */ + } + + /* Check if we need to rename this symbol. */ + if ((sp = lookup_symop_list(ecp, name, SYMOP_REDEF)) != NULL) + name = sp->newname; + + /* Check if we need to prefix the symbols. */ + newname = NULL; + if (ecp->prefix_sym != NULL && name != NULL && *name != '\0') { + namelen = strlen(name) + strlen(ecp->prefix_sym) + 1; + if ((newname = malloc(namelen)) == NULL) + err(EXIT_FAILURE, "malloc failed"); + snprintf(newname, namelen, "%s%s", ecp->prefix_sym, + name); + name = newname; + } + + /* Copy symbol, mark global/weak symbol and add to index map. */ + if (is_global_symbol(sym.st_info) || + is_weak_symbol(sym.st_info)) { + BIT_SET(gsym, i); + ecp->symndx[i] = sy_buf->ngs; + } else + ecp->symndx[i] = sy_buf->nls; + add_to_symtab(ecp, name, sym.st_value, sym.st_size, + sym.st_shndx, sym.st_info, sym.st_other, 0); + + if (newname != NULL) + free(newname); + + /* + * If the symbol is a STT_SECTION symbol, mark the section + * it points to. + */ + if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) + BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]); + } + + /* + * Give up if there is no real symbols inside the table. + * XXX The logic here needs to be improved. We need to + * check if that only local symbol is the reserved symbol. + */ + if (sy_buf->nls <= 1 && sy_buf->ngs == 0) + return (0); + + /* + * Create STT_SECTION symbols for sections that do not already + * got one. However, we do not create STT_SECTION symbol for + * .symtab, .strtab, .shstrtab and reloc sec of relocatables. + */ + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->pseudo) + continue; + if (strcmp(s->name, ".symtab") == 0 || + strcmp(s->name, ".strtab") == 0 || + strcmp(s->name, ".shstrtab") == 0) + continue; + if ((ecp->flags & RELOCATABLE) != 0 && + ((s->type == SHT_REL) || (s->type == SHT_RELA))) + continue; + + if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) + errx(EXIT_FAILURE, "elf_ndxscn failed: %s", + elf_errmsg(-1)); + + if (!BIT_ISSET(ecp->v_secsym, ndx)) { + sym.st_name = 0; + sym.st_value = s->vma; + sym.st_size = 0; + sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); + /* + * Don't let add_to_symtab() touch sym.st_shndx. + * In this case, we know the index already. + */ + add_to_symtab(ecp, NULL, sym.st_value, sym.st_size, + ndx, sym.st_info, sym.st_other, 1); + } + } + + /* + * Update st_name and index map for global/weak symbols. Note that + * global/weak symbols are put after local symbols. + */ + if (gsym != NULL) { + for(i = 0; (size_t) i < sc; i++) { + if (!BIT_ISSET(gsym, i)) + continue; + + /* Update st_name. */ + if (ec == ELFCLASS32) + sy_buf->g32[ecp->symndx[i]].st_name += + st_buf->lsz; + else + sy_buf->g64[ecp->symndx[i]].st_name += + st_buf->lsz; + + /* Update index map. */ + ecp->symndx[i] += sy_buf->nls; + } + free(gsym); + } + + return (1); +} + +void +create_symtab(struct elfcopy *ecp) +{ + struct section *s, *sy, *st; + size_t maxndx, ndx; + + sy = ecp->symtab; + st = ecp->strtab; + + /* + * Set section index map for .symtab and .strtab. We need to set + * these map because otherwise symbols which refer to .symtab and + * .strtab will be removed by symbol filtering unconditionally. + * And we have to figure out scn index this way (instead of calling + * elf_ndxscn) because we can not create Elf_Scn before we're certain + * that .symtab and .strtab will exist in the output object. + */ + maxndx = 0; + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->os == NULL) + continue; + if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) + errx(EXIT_FAILURE, "elf_ndxscn failed: %s", + elf_errmsg(-1)); + if (ndx > maxndx) + maxndx = ndx; + } + ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1; + ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2; + + /* + * Generate symbols for output object if SYMTAB_INTACT is not set. + * If there is no symbol in the input object or all the symbols are + * stripped, then free all the resouces allotted for symbol table, + * and clear SYMTAB_EXIST flag. + */ + if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { + TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); + TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); + free(ecp->symtab); + free(ecp->strtab); + ecp->symtab = NULL; + ecp->strtab = NULL; + ecp->flags &= ~SYMTAB_EXIST; + return; + } + + /* Create output Elf_Scn for .symtab and .strtab. */ + if ((sy->os = elf_newscn(ecp->eout)) == NULL || + (st->os = elf_newscn(ecp->eout)) == NULL) + errx(EXIT_FAILURE, "elf_newscn failed: %s", + elf_errmsg(-1)); + /* Update secndx anyway. */ + ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os); + ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os); + + /* + * Copy .symtab and .strtab section headers from input to output + * object to start with, these will be overridden later if need. + */ + copy_shdr(ecp, sy, ".symtab", 1, 0); + copy_shdr(ecp, st, ".strtab", 1, 0); + + /* Copy verbatim if symbol table is intact. */ + if (ecp->flags & SYMTAB_INTACT) { + copy_data(sy); + copy_data(st); + return; + } + + create_symtab_data(ecp); +} + +void +free_symtab(struct elfcopy *ecp) +{ + struct symbuf *sy_buf; + struct strbuf *st_buf; + + if (ecp->symtab != NULL && ecp->symtab->buf != NULL) { + sy_buf = ecp->symtab->buf; + if (sy_buf->l32 != NULL) + free(sy_buf->l32); + if (sy_buf->g32 != NULL) + free(sy_buf->g32); + if (sy_buf->l64 != NULL) + free(sy_buf->l64); + if (sy_buf->g64 != NULL) + free(sy_buf->g64); + } + + if (ecp->strtab != NULL && ecp->strtab->buf != NULL) { + st_buf = ecp->strtab->buf; + if (st_buf->l != NULL) + free(st_buf->l); + if (st_buf->g != NULL) + free(st_buf->g); + } +} + +void +create_external_symtab(struct elfcopy *ecp) +{ + struct section *s; + struct symbuf *sy_buf; + struct strbuf *st_buf; + GElf_Shdr sh; + size_t ndx; + + if (ecp->oec == ELFCLASS32) + ecp->symtab = create_external_section(ecp, ".symtab", NULL, + NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0); + else + ecp->symtab = create_external_section(ecp, ".symtab", NULL, + NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0); + + ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0, + SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0); + + /* Let sh_link field of .symtab section point to .strtab section. */ + if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + sh.sh_link = elf_ndxscn(ecp->strtab->os); + if (!gelf_update_shdr(ecp->symtab->os, &sh)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + + /* Create buffers for .symtab and .strtab. */ + if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + sy_buf->gcap = sy_buf->lcap = 64; + st_buf->gcap = 256; + st_buf->lcap = 64; + st_buf->lsz = 1; /* '\0' at start. */ + st_buf->gsz = 0; + + ecp->symtab->sz = 0; + ecp->strtab->sz = 0; + ecp->symtab->buf = sy_buf; + ecp->strtab->buf = st_buf; + + /* Always create the special symbol at the symtab beginning. */ + add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF, + ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1); + + /* Create STT_SECTION symbols. */ + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + if (s->pseudo) + continue; + if (strcmp(s->name, ".symtab") == 0 || + strcmp(s->name, ".strtab") == 0 || + strcmp(s->name, ".shstrtab") == 0) + continue; + (void) elf_errno(); + if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) { + warnx("elf_ndxscn failed: %s", + elf_errmsg(-1)); + continue; + } + add_to_symtab(ecp, NULL, 0, 0, ndx, + GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1); + } +} + +void +add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, + uint64_t st_size, uint16_t st_shndx, unsigned char st_info, + unsigned char st_other, int ndx_known) +{ + struct symbuf *sy_buf; + struct strbuf *st_buf; + int pos; + + /* + * Convenient macro for copying global/local 32/64 bit symbols + * from input object to the buffer created for output object. + * It handles buffer growing, st_name calculating and st_shndx + * updating for symbols with non-special section index. + */ +#define _ADDSYM(B, SZ) do { \ + if (sy_buf->B##SZ == NULL) { \ + sy_buf->B##SZ = malloc(sy_buf->B##cap * \ + sizeof(Elf##SZ##_Sym)); \ + if (sy_buf->B##SZ == NULL) \ + err(EXIT_FAILURE, "malloc failed"); \ + } else if (sy_buf->n##B##s >= sy_buf->B##cap) { \ + sy_buf->B##cap *= 2; \ + sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap * \ + sizeof(Elf##SZ##_Sym)); \ + if (sy_buf->B##SZ == NULL) \ + err(EXIT_FAILURE, "realloc failed"); \ + } \ + sy_buf->B##SZ[sy_buf->n##B##s].st_info = st_info; \ + sy_buf->B##SZ[sy_buf->n##B##s].st_other = st_other; \ + sy_buf->B##SZ[sy_buf->n##B##s].st_value = st_value; \ + sy_buf->B##SZ[sy_buf->n##B##s].st_size = st_size; \ + if (ndx_known) \ + sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ + else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE) \ + sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ + else \ + sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = \ + ecp->secndx[st_shndx]; \ + if (st_buf->B == NULL) { \ + st_buf->B = calloc(st_buf->B##cap, sizeof(*st_buf->B)); \ + if (st_buf->B == NULL) \ + err(EXIT_FAILURE, "malloc failed"); \ + } \ + if (name != NULL && *name != '\0') { \ + pos = lookup_exact_string(st_buf->B, \ + st_buf->B##sz, name); \ + if (pos != -1) \ + sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos; \ + else { \ + sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ + st_buf->B##sz; \ + while (st_buf->B##sz + strlen(name) >= \ + st_buf->B##cap - 1) { \ + st_buf->B##cap *= 2; \ + st_buf->B = realloc(st_buf->B, \ + st_buf->B##cap); \ + if (st_buf->B == NULL) \ + err(EXIT_FAILURE, \ + "realloc failed"); \ + } \ + strncpy(&st_buf->B[st_buf->B##sz], name, \ + strlen(name)); \ + st_buf->B[st_buf->B##sz + strlen(name)] = '\0'; \ + st_buf->B##sz += strlen(name) + 1; \ + } \ + } else \ + sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \ + sy_buf->n##B##s++; \ +} while (0) + + sy_buf = ecp->symtab->buf; + st_buf = ecp->strtab->buf; + + if (ecp->oec == ELFCLASS32) { + if (is_local_symbol(st_info)) + _ADDSYM(l, 32); + else + _ADDSYM(g, 32); + } else { + if (is_local_symbol(st_info)) + _ADDSYM(l, 64); + else + _ADDSYM(g, 64); + } + + /* Update section size. */ + ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) * + (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)); + ecp->strtab->sz = st_buf->lsz + st_buf->gsz; + +#undef _ADDSYM +} + +void +finalize_external_symtab(struct elfcopy *ecp) +{ + struct symbuf *sy_buf; + struct strbuf *st_buf; + int i; + + /* + * Update st_name for global/weak symbols. (global/weak symbols + * are put after local symbols) + */ + sy_buf = ecp->symtab->buf; + st_buf = ecp->strtab->buf; + for (i = 0; (size_t) i < sy_buf->ngs; i++) { + if (ecp->oec == ELFCLASS32) + sy_buf->g32[i].st_name += st_buf->lsz; + else + sy_buf->g64[i].st_name += st_buf->lsz; + } +} + +void +create_symtab_data(struct elfcopy *ecp) +{ + struct section *sy, *st; + struct symbuf *sy_buf; + struct strbuf *st_buf; + Elf_Data *gsydata, *lsydata, *gstdata, *lstdata; + GElf_Shdr shy, sht; + + sy = ecp->symtab; + st = ecp->strtab; + + if (gelf_getshdr(sy->os, ­) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + if (gelf_getshdr(st->os, &sht) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", + elf_errmsg(-1)); + + /* + * Create two Elf_Data for .symtab section of output object, one + * for local symbols and another for global symbols. Note that + * local symbols appear first in the .symtab. + */ + sy_buf = sy->buf; + if (sy_buf->nls > 0) { + if ((lsydata = elf_newdata(sy->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + if (ecp->oec == ELFCLASS32) { + lsydata->d_align = 4; + lsydata->d_off = 0; + lsydata->d_buf = sy_buf->l32; + lsydata->d_size = sy_buf->nls * + sizeof(Elf32_Sym); + lsydata->d_type = ELF_T_SYM; + lsydata->d_version = EV_CURRENT; + } else { + lsydata->d_align = 8; + lsydata->d_off = 0; + lsydata->d_buf = sy_buf->l64; + lsydata->d_size = sy_buf->nls * + sizeof(Elf64_Sym); + lsydata->d_type = ELF_T_SYM; + lsydata->d_version = EV_CURRENT; + } + } + if (sy_buf->ngs > 0) { + if ((gsydata = elf_newdata(sy->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + if (ecp->oec == ELFCLASS32) { + gsydata->d_align = 4; + gsydata->d_off = sy_buf->nls * + sizeof(Elf32_Sym); + gsydata->d_buf = sy_buf->g32; + gsydata->d_size = sy_buf->ngs * + sizeof(Elf32_Sym); + gsydata->d_type = ELF_T_SYM; + gsydata->d_version = EV_CURRENT; + } else { + gsydata->d_align = 8; + gsydata->d_off = sy_buf->nls * + sizeof(Elf64_Sym); + gsydata->d_buf = sy_buf->g64; + gsydata->d_size = sy_buf->ngs * + sizeof(Elf64_Sym); + gsydata->d_type = ELF_T_SYM; + gsydata->d_version = EV_CURRENT; + } + } + + /* + * Create two Elf_Data for .strtab, one for local symbol name + * and another for globals. Same as .symtab, local symbol names + * appear first. + */ + st_buf = st->buf; + if ((lstdata = elf_newdata(st->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + lstdata->d_align = 1; + lstdata->d_off = 0; + lstdata->d_buf = st_buf->l; + lstdata->d_size = st_buf->lsz; + lstdata->d_type = ELF_T_BYTE; + lstdata->d_version = EV_CURRENT; + + if (st_buf->gsz > 0) { + if ((gstdata = elf_newdata(st->os)) == NULL) + errx(EXIT_FAILURE, "elf_newdata() failed: %s.", + elf_errmsg(-1)); + gstdata->d_align = 1; + gstdata->d_off = lstdata->d_size; + gstdata->d_buf = st_buf->g; + gstdata->d_size = st_buf->gsz; + gstdata->d_type = ELF_T_BYTE; + gstdata->d_version = EV_CURRENT; + } + + shy.sh_addr = 0; + shy.sh_addralign = (ecp->oec == ELFCLASS32 ? 4 : 8); + shy.sh_size = sy->sz; + shy.sh_type = SHT_SYMTAB; + shy.sh_flags = 0; + shy.sh_entsize = gelf_fsize(ecp->eout, ELF_T_SYM, 1, + EV_CURRENT); + /* + * According to SYSV abi, here sh_info is one greater than + * the symbol table index of the last local symbol(binding + * STB_LOCAL). + */ + shy.sh_info = sy_buf->nls; + + sht.sh_addr = 0; + sht.sh_addralign = 1; + sht.sh_size = st->sz; + sht.sh_type = SHT_STRTAB; + sht.sh_flags = 0; + sht.sh_entsize = 0; + sht.sh_info = 0; + sht.sh_link = 0; + + if (!gelf_update_shdr(sy->os, ­)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); + if (!gelf_update_shdr(st->os, &sht)) + errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", + elf_errmsg(-1)); +} + +void +add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname, + unsigned int op) +{ + struct symop *s; + + if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) { + if ((s = calloc(1, sizeof(*s))) == NULL) + errx(EXIT_FAILURE, "not enough memory"); + s->name = name; + if (op == SYMOP_REDEF) + s->newname = newname; + } + + s->op |= op; + STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list); +} + +static int +match_wildcard(const char *name, const char *pattern) +{ + int reverse, match; + + reverse = 0; + if (*pattern == '!') { + reverse = 1; + pattern++; + } + + match = 0; + if (!fnmatch(pattern, name, 0)) { + match = 1; + printf("string '%s' match to pattern '%s'\n", name, pattern); + } + + return (reverse ? !match : match); +} + +struct symop * +lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) +{ + struct symop *s; + + STAILQ_FOREACH(s, &ecp->v_symop, symop_list) { + if (name == NULL || !strcmp(name, s->name) || + ((ecp->flags & WILDCARD) && match_wildcard(name, s->name))) + if ((s->op & op) != 0) + return (s); + } + + return (NULL); +} + +static int +lookup_exact_string(const char *buf, size_t sz, const char *s) +{ + const char *b; + size_t slen; + + slen = strlen(s); + for (b = buf; b < buf + sz; b += strlen(b) + 1) { + if (strlen(b) != slen) + continue; + if (!strcmp(b, s)) + return (b - buf); + } + + return (-1); +} diff --git a/contrib/elftoolchain/libelftc/Makefile b/contrib/elftoolchain/libelftc/Makefile new file mode 100644 index 000000000000..a5fc2975097f --- /dev/null +++ b/contrib/elftoolchain/libelftc/Makefile @@ -0,0 +1,65 @@ +# $Id: Makefile 2859 2013-01-05 09:21:54Z jkoshy $ + +TOP= ${.CURDIR}/.. + +LIB= elftc + +SRCS= elftc_bfdtarget.c \ + elftc_copyfile.c \ + elftc_demangle.c \ + elftc_set_timestamps.c \ + elftc_string_table.c \ + elftc_version.c \ + libelftc_bfdtarget.c \ + libelftc_dem_arm.c \ + libelftc_dem_gnu2.c \ + libelftc_dem_gnu3.c \ + libelftc_hash.c \ + libelftc_vstr.c + +INCS= libelftc.h +INCSDIR= /usr/include + +RELEASE= HEAD # Change this on release branches. + +SHLIB_MAJOR= 1 + +WARNS?= 6 + +CLEANFILES+= elftc_version.c + +LDADD+= -lelf + +MAN= elftc.3 \ + elftc_bfd_find_target.3 \ + elftc_copyfile.3 \ + elftc_demangle.3 \ + elftc_set_timestamps.3 \ + elftc_string_table_create.3 \ + elftc_version.3 + +MLINKS= elftc_bfd_find_target.3 elftc_bfd_target_byteorder.3 \ + elftc_bfd_find_target.3 elftc_bfd_target_class.3 \ + elftc_bfd_find_target.3 elftc_bfd_target_flavor.3 \ + elftc_string_table_create.3 elftc_string_table_from_section.3 \ + elftc_string_table_create.3 elftc_string_table_destroy.3 \ + elftc_string_table_create.3 elftc_string_table_image.3 \ + elftc_string_table_create.3 elftc_string_table_insert.3 \ + elftc_string_table_create.3 elftc_string_table_lookup.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_create_nested.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_delete_name.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_delete_entry.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_destroy.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_from_section.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_insert.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_iterate.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_lookup.3 \ + elftc_symbol_table_create.3 elftc_symbol_table_to_image.3 + +.if !make(clean) && !make(clobber) +.BEGIN: .SILENT + ${.CURDIR}/make-toolchain-version -t ${TOP} -r ${RELEASE} \ + -h ${OS_HOST} +.endif + +.include "${TOP}/mk/elftoolchain.lib.mk" diff --git a/contrib/elftoolchain/libelftc/Version.map b/contrib/elftoolchain/libelftc/Version.map new file mode 100644 index 000000000000..43f9e823b407 --- /dev/null +++ b/contrib/elftoolchain/libelftc/Version.map @@ -0,0 +1,18 @@ +/* + * $Id: Version.map 2574 2012-09-11 15:11:59Z jkoshy $ + */ + +R1.0 { +global: + elftc_bfd_find_target; + elftc_bfd_target_byteorder; + elftc_bfd_target_class; + elftc_bfd_target_flavor; + elftc_bfd_target_machine; + elftc_copyfile; + elftc_demangle; + elftc_set_timestamps; + elftc_version; +local: + *; +}; diff --git a/contrib/elftoolchain/libelftc/_libelftc.h b/contrib/elftoolchain/libelftc/_libelftc.h new file mode 100644 index 000000000000..c300f9105aee --- /dev/null +++ b/contrib/elftoolchain/libelftc/_libelftc.h @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2009 Kai Wang + * Copyright (c) 2007,2008 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: _libelftc.h 2856 2013-01-04 16:00:26Z jkoshy $ + */ + +#ifndef __LIBELFTC_H_ +#define __LIBELFTC_H_ + +#include + +#include "_elftc.h" + +struct _Elftc_Bfd_Target { + const char *bt_name; /* target name. */ + unsigned int bt_type; /* target type. */ + unsigned int bt_byteorder; /* elf target byteorder. */ + unsigned int bt_elfclass; /* elf target class (32/64bit). */ + unsigned int bt_machine; /* elf target arch. */ + unsigned int bt_osabi; /* elf target abi. */ +}; + +extern struct _Elftc_Bfd_Target _libelftc_targets[]; + +/** @brief Dynamic vector data for string. */ +struct vector_str { + /** Current size */ + size_t size; + /** Total capacity */ + size_t capacity; + /** String array */ + char **container; +}; + +#define BUFFER_GROWFACTOR 1.618 + +#define ELFTC_FAILURE 0 +#define ELFTC_ISDIGIT(C) (isdigit((C) & 0xFF)) +#define ELFTC_SUCCESS 1 + +#define VECTOR_DEF_CAPACITY 8 + + +__BEGIN_DECLS +char *cpp_demangle_ARM(const char *_org); +char *cpp_demangle_gnu2(const char *_org); +char *cpp_demangle_gnu3(const char *_org); +bool is_cpp_mangled_ARM(const char *_org); +bool is_cpp_mangled_gnu2(const char *_org); +bool is_cpp_mangled_gnu3(const char *_org); +unsigned int libelftc_hash_string(const char *); +void vector_str_dest(struct vector_str *_vec); +int vector_str_find(const struct vector_str *_vs, const char *_str, + size_t _len); +char *vector_str_get_flat(const struct vector_str *_vs, size_t *_len); +bool vector_str_init(struct vector_str *_vs); +bool vector_str_pop(struct vector_str *_vs); +bool vector_str_push(struct vector_str *_vs, const char *_str, + size_t _len); +bool vector_str_push_vector_head(struct vector_str *_dst, + struct vector_str *_org); +char *vector_str_substr(const struct vector_str *_vs, size_t _begin, + size_t _end, size_t *_rlen); +__END_DECLS + +#endif /* __LIBELFTC_H */ diff --git a/contrib/elftoolchain/libelftc/elftc.3 b/contrib/elftoolchain/libelftc/elftc.3 new file mode 100644 index 000000000000..bbf51738bb20 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc.3 @@ -0,0 +1,83 @@ +.\" Copyright (c) 2012 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc.3 2818 2012-12-24 12:32:48Z jkoshy $ +.\" +.Dd December 24, 2012 +.Os +.Dt ELFTC 3 +.Sh NAME +.Nm elftc +.Nd support routines used in the Elftoolchain project +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Sh DESCRIPTION +The +.Lb libelftc +provides support routines used for developing the utilities in the +Elftoolchain source tree. +.Pp +This manual page serves as an overview of the functionality in this +library. +Additional reference information may be found in the individual +manual pages for the functions listed below. +.Ss Functional Grouping +.Bl -tag -width indent +.It "Binary Object Handling" +.Bl -tag -compact +.It Fn elftc_bfd_find_target +Locate a binary object descriptor. +.It Fn elftc_bfd_target_class +Query the ELF class for a binary object descriptor. +.It Fn elftc_bfd_target_byteorder +Query the byte order for a binary object descriptor. +.It Fn elftc_bfd_target_flavor +Query the object format for a binary object descriptor. +.It Fn elftc_bfd_target_machine +Query the target machine for a binary object descriptor. +.El +.It "C++ support" +.Bl -tag -compact +.It Fn elftc_demangle +Decodes a symbol name encoded according to the encoding rules for the +C++ language. +.El +.It "Programming conveniences" +.Bl -tag -compact +.It Fn elftc_copyfile +Copies the contents of a file to another. +.It Fn elftc_set_timestamp +Portably set the time stamps on a file. +.El +.It "Project Configuration" +.Bl -tag -compact +.It Fn elftc_version +Returns a project-wide identifier string that encodes the source +revision of the source tree. +.El +.El +.Sh SEE ALSO +.Xr dwarf 3 , +.Xr elf 3 diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 new file mode 100644 index 000000000000..851ae314ea7e --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 @@ -0,0 +1,189 @@ +.\" Copyright (c) 2010-2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_bfd_find_target.3 2251 2011-11-30 16:50:06Z jkoshy $ +.\" +.Dd November 30, 2011 +.Os +.Dt ELFTC_BFD_FIND_TARGET +.Sh NAME +.Nm elftc_bfd_find_target , +.Nm elftc_bfd_target_byteorder , +.Nm elftc_bfd_target_class , +.Nm elftc_bfd_target_flavor , +.Nm elftc_bfd_target_machine +.Nd binary object descriptor handling +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Vt struct Elftc_Bfd_Target; +.Ft "Elftc_Bfd_Target *" +.Fn elftc_bfd_find_target "const char *target_name" +.Ft "unsigned int" +.Fn elftc_bfd_target_class "Elftc_Bfd_Target *target" +.Ft "unsigned int" +.Fn elftc_bfd_target_byteorder "Elftc_Bfd_Target *target" +.Ft Elftc_Bfd_Target_Flavor +.Fn elftc_bfd_target_flavor "Elftc_Bfd_Target *target" +.Ft "unsigned int" +.Fn elftc_bfd_target_machine "Elftc_Bfd_Target *target" +.Sh DESCRIPTION +Function +.Fn elftc_bfd_find_target +locates a binary object descriptor corresponding to the descriptor +name in argument +.Ar "target_name" . +Binary object descriptors encapsulate properties of an object format +such as its file representation, ELF class, and byte endianness. +.Pp +Known descriptor names and their properties include: +.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "ELF Class" +.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "ELF Class" +.It Li binary Ta Binary Ta - Ta - +.It Li elf32-avr Ta ELF Ta LSB Ta 32 +.It Li elf32-big Ta ELF Ta MSB Ta 32 +.It Li elf32-bigarm Ta ELF Ta MSB Ta 32 +.It Li elf32-bigmips Ta ELF Ta MSB Ta 32 +.It Li elf32-i386 Ta ELF Ta LSB Ta 32 +.It Li elf32-i386-freebsd Ta ELF Ta LSB Ta 32 +.It Li elf32-ia64-big Ta ELF Ta MSB Ta 32 +.It Li elf32-little Ta ELF Ta LSB Ta 32 +.It Li elf32-littlearm Ta ELF Ta LSB Ta 32 +.It Li elf32-littlemips Ta ELF Ta LSB Ta 32 +.It Li elf32-powerpc Ta ELF Ta MSB Ta 32 +.It Li elf32-powerpcle Ta ELF Ta LSB Ta 32 +.It Li elf32-sh Ta ELF Ta MSB Ta 32 +.It Li elf32-shl Ta ELF Ta LSB Ta 32 +.It Li elf32-sh-nbsd Ta ELF Ta MSB Ta 32 +.It Li elf32-shl-nbsd Ta ELF Ta LSB Ta 32 +.It Li elf32-shbig-linux Ta ELF Ta MSB Ta 32 +.It Li elf32-shl-linux Ta ELF Ta LSB Ta 32 +.It Li elf32-sparc Ta ELF Ta MSB Ta 32 +.It Li elf64-alpha Ta ELF Ta LSB Ta 64 +.It Li elf64-alpha-freebsd Ta ELF Ta LSB Ta 64 +.It Li elf64-big Ta ELF Ta MSB Ta 64 +.It Li elf64-bigmips Ta ELF Ta MSB Ta 64 +.It Li elf64-ia64-big Ta ELF Ta MSB Ta 64 +.It Li elf64-ia64-little Ta ELF Ta LSB Ta 64 +.It Li elf64-little Ta ELF Ta LSB Ta 64 +.It Li elf64-littlemips Ta ELF Ta LSB Ta 64 +.It Li elf64-powerpc Ta ELF Ta MSB Ta 64 +.It Li elf64-powerpcle Ta ELF Ta LSB Ta 64 +.It Li elf64-sh64 Ta ELF Ta MSB Ta 64 +.It Li elf64-sh64l Ta ELF Ta LSB Ta 64 +.It Li elf64-sh64-nbsd Ta ELF Ta MSB Ta 64 +.It Li elf64-sh64l-nbsd Ta ELF Ta LSB Ta 64 +.It Li elf64-sh64big-linux Ta ELF Ta MSB Ta 64 +.It Li elf64-sh64-linux Ta ELF Ta LSB Ta 64 +.It Li elf64-sparc Ta ELF Ta MSB Ta 64 +.It Li elf64-sparc-freebsd Ta ELF Ta MSB Ta 64 +.It Li elf64-x86-64 Ta ELF Ta LSB Ta 64 +.It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64 +.It Li ihex Ta IHEX Ta - Ta - +.It Li srec Ta SREC Ta - Ta - +.It Li symbolsrec Ta SREC Ta - Ta - +.El +.Pp +Function +.Fn elftc_bfd_target_byteorder +returns the ELF byte order associated with target descriptor +.Ar target . +.Pp +Function +.Fn elftc_bfd_target_class +returns the ELF class associated with target descriptor +.Ar target . +.Pp +Function +.Fn elftc_bfd_target_flavor +returns the object format associated with target descriptor +.Ar target . +The known object formats are: +.Bl -tag -offset "XXXX" -width ".Dv ETF_BINARY" -compact +.It Dv ETF_ELF +An ELF object. +.It Dv ETF_BINARY +Raw binary. +.It Dv ETF_IHEX +An object encoded in +.Tn Intel +hex format. +.It Dv ETF_NONE +An unknown object format. +.It Dv ETF_SREC +An object encoded as S-records. +.El +.Sh RETURN VALUES +Function +.Fn elftc_bfd_find_target +returns a valid pointer to an opaque binary target descriptor if +successful, or NULL in case of an error. +.Pp +Function +.Fn elftc_bfd_target_byteorder +returns the ELF byte order associated with the target descriptor; one of +.Dv ELFDATA2MSB +or +.Dv ELFDATA2LSB . +.Pp +Function +.Fn elftc_bfd_target_class +returns the ELF class associated with the target descriptor; one of +.Dv ELFCLASS32 +or +.Dv ELFCLASS64 . +.Pp +Function +.Fn elftc_bfd_target_machine +returns the ELF architecture associated with the target descriptor. +.Pp +Function +.Fn elftc_bfd_target_flavor +returns one of +.Dv ETF_BINARY , +.Dv ETF_ELF , +.Dv ETF_IHEX +or +.Dv ETF_SREC +if successful or +.Dv ETF_NONE +in case of error. +.Sh EXAMPLES +To return descriptor information associated with target name +.Dq elf64-big +use: +.Bd -literal -offset indent +struct Elftc_Bfd_Target *t; + +if ((t = elftc_bfd_find_target("elf64-big")) == NULL) + errx(EXIT_FAILURE, "Cannot find target descriptor"); + +printf("Class: %s\\n", elftc_bfd_target_class(t) == ELFCLASS32 ? + "ELFCLASS32" : "ELFCLASS64"); +printf("Byteorder: %s\\n", + elftc_bfd_target_byteorder(t) == ELFDATA2LSB ? "LSB" : "MSB"); +printf("Flavor: %d\\n", elftc_bfd_target_flavor(t)); +.Ed +.Sh SEE ALSO +.Xr elf 3 diff --git a/contrib/elftoolchain/libelftc/elftc_bfdtarget.c b/contrib/elftoolchain/libelftc/elftc_bfdtarget.c new file mode 100644 index 000000000000..351e5e467e67 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_bfdtarget.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2008,2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: elftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $"); + +Elftc_Bfd_Target * +elftc_bfd_find_target(const char *tgt_name) +{ + Elftc_Bfd_Target *tgt; + + for (tgt = _libelftc_targets; tgt->bt_name; tgt++) + if (!strcmp(tgt_name, tgt->bt_name)) + return (tgt); + + return (NULL); /* not found */ +} + +Elftc_Bfd_Target_Flavor +elftc_bfd_target_flavor(Elftc_Bfd_Target *tgt) +{ + + return (tgt->bt_type); +} + +unsigned int +elftc_bfd_target_byteorder(Elftc_Bfd_Target *tgt) +{ + + return (tgt->bt_byteorder); +} + +unsigned int +elftc_bfd_target_class(Elftc_Bfd_Target *tgt) +{ + + return (tgt->bt_elfclass); +} + +unsigned int +elftc_bfd_target_machine(Elftc_Bfd_Target *tgt) +{ + + return (tgt->bt_machine); +} diff --git a/contrib/elftoolchain/libelftc/elftc_copyfile.3 b/contrib/elftoolchain/libelftc/elftc_copyfile.3 new file mode 100644 index 000000000000..45204338bac7 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_copyfile.3 @@ -0,0 +1,73 @@ +.\" Copyright (c) 2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_copyfile.3 2315 2011-12-11 09:28:55Z jkoshy $ +.\" +.Dd December 11, 2011 +.Os +.Dt ELFTC_COPYFILE 3 +.Sh NAME +.Nm elftc_copyfile +.Nd convenience function to copy data +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Ft in +.Fn elftc_copyfile "int ifd" "int ofd" +.Sh DESCRIPTION +The function +.Fn elftc_copyfile +copies the contents of the file referenced by argument +.Ar ifd +to the file referenced by argument +.Ar ofd . +.Pp +The argument +.Ar ifd +should contain a file descriptor opened for reading, with its file +offset at the beginning of the file. +.Pp +The argument +.Ar ofd +should contain a file descriptor opened for writing. +.Sh RETURN VALUE +.Rv -std +.Sh ERRORS +The function +.Fn elftc_copyfile +may fail with any of the errors returned by +.Xr fstat 2 , +.Xr malloc 3 , +.Xr mmap 2 , +.Xr munmap 2 , +.Xr read 2 +or +.Xr write 2 . +.Sh SEE ALSO +.Xr fstat 2 , +.Xr malloc 3 , +.Xr mmap 2 , +.Xr munmap 2 , +.Xr read 2 , +.Xr write 2 diff --git a/contrib/elftoolchain/libelftc/elftc_copyfile.c b/contrib/elftoolchain/libelftc/elftc_copyfile.c new file mode 100644 index 000000000000..0bacaf45e769 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_copyfile.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2011, Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#include "libelftc.h" +#include "_libelftc.h" + +#if ELFTC_HAVE_MMAP +#include +#endif + +ELFTC_VCSID("$Id: elftc_copyfile.c 2318 2011-12-11 10:54:27Z jkoshy $"); + +/* + * Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on + * success and -1 on error. + */ + +int +elftc_copyfile(int ifd, int ofd) +{ + int buf_mmapped; + struct stat sb; + char *b, *buf; + ssize_t nw; + size_t n; + + /* Determine the input file's size. */ + if (fstat(ifd, &sb) < 0) + return (-1); + + /* Skip files without content. */ + if (sb.st_size == 0) + return (0); + + buf = NULL; + buf_mmapped = 0; + +#if ELFTC_HAVE_MMAP + /* + * Prefer mmap() if it is available. + */ + buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0); + if (buf != MAP_FAILED) + buf_mmapped = 1; + else + buf = NULL; +#endif + + /* + * If mmap() is not available, or if the mmap() operation + * failed, allocate a buffer, and read in input data. + */ + if (buf == NULL) { + if ((buf = malloc(sb.st_size)) == NULL) + return (-1); + if (read(ifd, buf, sb.st_size) != sb.st_size) + return (-1); + } + + /* + * Write data to the output file descriptor. + */ + for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw) + if ((nw = write(ofd, b, n)) <= 0) + break; + + /* Release the input buffer. */ +#if ELFTC_HAVE_MMAP + if (buf_mmapped && munmap(buf, sb.st_size) < 0) + return (-1); +#endif + + if (!buf_mmapped) + free(buf); + + return (n > 0 ? -1 : 0); +} + diff --git a/contrib/elftoolchain/libelftc/elftc_demangle.3 b/contrib/elftoolchain/libelftc/elftc_demangle.3 new file mode 100644 index 000000000000..bbe67e52df0d --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_demangle.3 @@ -0,0 +1,116 @@ +.\" Copyright (c) 2009,2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_demangle.3 2065 2011-10-26 15:24:47Z jkoshy $ +.\" +.Dd August 24, 2011 +.Os +.Dt ELFTC_DEMANGLE 3 +.Sh NAME +.Nm elftc_demangle +.Nd demangle a C++ name +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Ft int +.Fo elftc_demangle +.Fa "const char *encodedname" +.Fa "char *buffer" +.Fa "size_t bufsize" +.Fa "unsigned int flags" +.Fc +.Sh DESCRIPTION +Function +.Fn elftc_demangle +decodes a symbol name encoded according to the type encoding rules +for the C++ language and returns a string denoting an equivalent +C++ prototype. +.Pp +Argument +.Ar encodedname +specifies the encoded symbol name. +Argument +.Ar buffer +denotes a programmer-specified area to place the prototype string in. +Argument +.Ar bufsize +specifies the size of the programmer-specified area. +Argument +.Ar flags +specifies the encoding style in use for argument +.Ar encodedname . +Supported encoding styles are: +.Bl -tag -width ".Dv ELFTC_DEM_GNU3" +.It Dv ELFTC_DEM_ARM +The encoding style used by compilers adhering to the conventions of the +C++ Annotated Reference Manual. +.It Dv ELFTC_DEM_GNU2 +The encoding style by GNU C++ version 2. +.It Dv ELFTC_DEM_GNU3 +The encoding style by GNU C++ version 3 and later. +.El +.Pp +Argument +.Ar flags +may be zero, in which case the function will attempt to guess the +encoding scheme from the contents of +.Ar encodedname . +.Sh RETURN VALUE +Function +.Fn elftc_demangle +returns 0 on success. +In case of an error it returns -1 and sets the +.Va errno +variable. +.Sh EXAMPLES +To decode a name that uses an unknown encoding style use: +.Bd -literal -offset indent +char buffer[1024]; +const char *funcname; + +funcname = ...; /* points to string to be demangled */ +if (elftc_demangle(funcname, buffer, sizeof(buffer), 0) == 0) + printf("Demangled name: %\\n", buffer); +else + perror("Cannot demangle %s", funcname); +.Ed +.Sh ERRORS +Function +.Fn elftc_demangle +may fail with the following errors: +.Bl -tag -width ".Bq Er ENAMETOOLONG" +.It Bq Er EINVAL +Argument +.Ar encodedname +was not a valid encoded name. +.It Bq Er ENAMETOOLONG +The output buffer specified by arguments +.Ar buffer +and +.Ar bufsize +was too small to hold the decoded function prototype. +.El +.Sh SEE ALSO +.Xr elf 3 , +.Xr elf_strptr 3 diff --git a/contrib/elftoolchain/libelftc/elftc_demangle.c b/contrib/elftoolchain/libelftc/elftc_demangle.c new file mode 100644 index 000000000000..c55564e3df63 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_demangle.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: elftc_demangle.c 2065 2011-10-26 15:24:47Z jkoshy $"); + +static int +is_mangled(const char *s, int style) +{ + + switch (style) { + case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0); + case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0); + case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0); + } + + /* No style or invalid style spcified, try to guess. */ + if (is_cpp_mangled_gnu3(s)) + return (ELFTC_DEM_GNU3); + if (is_cpp_mangled_gnu2(s)) + return (ELFTC_DEM_GNU2); + if (is_cpp_mangled_ARM(s)) + return (ELFTC_DEM_ARM); + + /* Cannot be demangled. */ + return (0); +} + +static char * +demangle(const char *s, int style, int rc) +{ + + (void) rc; /* XXX */ + switch (style) { + case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s)); + case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s)); + case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s)); + default: + assert(0); + return (NULL); + } +} + +int +elftc_demangle(const char *mangledname, char *buffer, size_t bufsize, + unsigned int flags) +{ + int style, rc; + char *rlt; + + style = flags & 0xFFFF; + rc = flags >> 16; + + if (mangledname == NULL || + ((style = is_mangled(mangledname, style)) == 0)) { + errno = EINVAL; + return (-1); + } + + if ((rlt = demangle(mangledname, style, rc)) == NULL) { + errno = EINVAL; + return (-1); + } + + if (buffer == NULL || bufsize < strlen(rlt) + 1) { + free(rlt); + errno = ENAMETOOLONG; + return (-1); + } + + strncpy(buffer, rlt, bufsize); + buffer[bufsize - 1] = '\0'; + free(rlt); + + return (0); +} diff --git a/contrib/elftoolchain/libelftc/elftc_set_timestamps.3 b/contrib/elftoolchain/libelftc/elftc_set_timestamps.3 new file mode 100644 index 000000000000..115fe92707a3 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_set_timestamps.3 @@ -0,0 +1,84 @@ +.\" Copyright (c) 2011 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id$ +.\" +.Dd December 15, 2011 +.Os +.Dt ELFTC_SET_TIMESTAMPS 3 +.Sh NAME +.Nm elftc_set_timestamps +.Nd set file timestamps +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Ft int +.Fn elftc_set_timestamps "const char *filename" "struct stat *sb" +.Sh DESCRIPTION +The +.Fn elftc_set_timestamps +function is used to set the access and modified time stamps on a file +based on the contents of a +.Vt "struct stat" +descriptor. +.Pp +Argument +.Ar filename +names an existing file in the file system. +.Pp +Argument +.Ar sb +points to structure of type +.Vt "struct stat" +populated by a prior call to +.Xr fstat 2 +or +.Xr stat 2 . +.Sh IMPLEMENTATION NOTES +This function will invoke the high-resolution +.Xr utimes 2 +system call if the underlying operating system supports it. +On operating systems lacking support for +.Xr utimes 2 , +the function will use lower resolution +.Xr utime 2 +system call. +.Sh EXAMPLES +To set the access and modified times for a new file to those of an +existing file, use: +.Bd -literal -offset indent +struct stat sb; +const char *existing_filename, *new_filename; + +if (stat(existing_filename, &sb) < 0) + err(EXIT_FAILURE, "stat failed"); + +if (elftc_set_timestamps(new_filename, &sb) < 0) + err(EXIT_FAILURE, "timestamps could not be set"); +.Ed +.Sh SEE ALSO +.Xr fstat 2 , +.Xr stat 2 , +.Xr utime 2 , +.Xr utimes 2 . diff --git a/contrib/elftoolchain/libelftc/elftc_set_timestamps.c b/contrib/elftoolchain/libelftc/elftc_set_timestamps.c new file mode 100644 index 000000000000..cb28c351e0d4 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_set_timestamps.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2011 Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "libelftc.h" + +#include "_libelftc.h" + +ELFTC_VCSID("$Id$"); + +/* + * Determine the field name for the timestamp fields inside a 'struct + * stat'. + */ + +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define ATIME st_atimespec +#define MTIME st_mtimespec +#define LIBELFTC_HAVE_UTIMES 1 +#endif + +#if defined(__DragonFly__) || defined(__linux__) || defined(__OpenBSD__) +#define ATIME st_atim +#define MTIME st_mtim +#define LIBELFTC_HAVE_UTIMES 1 +#endif + +#if LIBELFTC_HAVE_UTIMES +#include +#else +#include +#endif + +int +elftc_set_timestamps(const char *fn, struct stat *sb) +{ +#if LIBELFTC_HAVE_UTIMES + /* + * The BSD utimes() system call offers timestamps + * 1-microsecond granularity. + */ + struct timeval tv[2]; + + tv[0].tv_sec = sb->ATIME.tv_sec; + tv[0].tv_usec = sb->ATIME.tv_nsec / 1000; + tv[1].tv_sec = sb->MTIME.tv_sec; + tv[1].tv_usec = sb->MTIME.tv_nsec / 1000; + + return (utimes(fn, tv)); +#else + /* + * On OSes without utimes(), fall back to the POSIX utime() + * call, which offers 1-second granularity. + */ + struct utimbuf utb; + + utb.actime = sb->st_atime; + utb.modtime = sb->st_mtime; + return (utime(fn, &utb)); +#endif +} diff --git a/contrib/elftoolchain/libelftc/elftc_string_table.c b/contrib/elftoolchain/libelftc/elftc_string_table.c new file mode 100644 index 000000000000..bba9ac6a76cd --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_string_table.c @@ -0,0 +1,392 @@ +/*- + * Copyright (c) 2013, Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "libelftc.h" +#include "_libelftc.h" + +ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $"); + +#define ELFTC_STRING_TABLE_DEFAULT_SIZE (4*1024) +#define ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE 16 +#define ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH 8 +#define ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT (4*1024) + +struct _Elftc_String_Table_Entry { + int ste_idx; + SLIST_ENTRY(_Elftc_String_Table_Entry) ste_next; +}; + +#define ELFTC_STRING_TABLE_COMPACTION_FLAG 0x1 +#define ELFTC_STRING_TABLE_LENGTH(st) ((st)->st_len >> 1) +#define ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st) do { \ + (st)->st_len &= ~ELFTC_STRING_TABLE_COMPACTION_FLAG; \ + } while (0) +#define ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st) do { \ + (st)->st_len |= ELFTC_STRING_TABLE_COMPACTION_FLAG; \ + } while (0) +#define ELFTC_STRING_TABLE_UPDATE_LENGTH(st, len) do { \ + (st)->st_len = \ + ((st)->st_len & \ + ELFTC_STRING_TABLE_COMPACTION_FLAG) | \ + ((len) << 1); \ + } while (0) + +struct _Elftc_String_Table { + unsigned int st_len; /* length and flags */ + int st_nbuckets; + int st_string_pool_size; + char *st_string_pool; + SLIST_HEAD(_Elftc_String_Table_Bucket, + _Elftc_String_Table_Entry) st_buckets[]; +}; + +static struct _Elftc_String_Table_Entry * +elftc_string_table_find_hash_entry(Elftc_String_Table *st, const char *string, + int *rhashindex) +{ + struct _Elftc_String_Table_Entry *ste; + int hashindex; + char *s; + + hashindex = libelftc_hash_string(string) % st->st_nbuckets; + + if (rhashindex) + *rhashindex = hashindex; + + SLIST_FOREACH(ste, &st->st_buckets[hashindex], ste_next) { + s = st->st_string_pool + abs(ste->ste_idx); + + assert(s > st->st_string_pool && + s < st->st_string_pool + st->st_string_pool_size); + + if (strcmp(s, string) == 0) + return (ste); + } + + return (NULL); +} + +static int +elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string) +{ + char *newpool; + int len, newsize, stlen; + + len = strlen(string) + 1; /* length, including the trailing NUL */ + stlen = ELFTC_STRING_TABLE_LENGTH(st); + + /* Resize the pool, if needed. */ + if (stlen + len >= st->st_string_pool_size) { + newsize = roundup(st->st_string_pool_size + + ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT, + ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT); + if ((newpool = realloc(st->st_string_pool, newsize)) == + NULL) + return (0); + st->st_string_pool = newpool; + st->st_string_pool_size = newsize; + } + + strcpy(st->st_string_pool + stlen, string); + ELFTC_STRING_TABLE_UPDATE_LENGTH(st, stlen + len); + + return (stlen); +} + +Elftc_String_Table * +elftc_string_table_create(int sizehint) +{ + int n, nbuckets, tablesize; + struct _Elftc_String_Table *st; + + if (sizehint < ELFTC_STRING_TABLE_DEFAULT_SIZE) + sizehint = ELFTC_STRING_TABLE_DEFAULT_SIZE; + + nbuckets = sizehint / (ELFTC_STRING_TABLE_EXPECTED_CHAIN_LENGTH * + ELFTC_STRING_TABLE_EXPECTED_STRING_SIZE); + + tablesize = sizeof(struct _Elftc_String_Table) + + nbuckets * sizeof(struct _Elftc_String_Table_Bucket); + + if ((st = malloc(tablesize)) == NULL) + return (NULL); + if ((st->st_string_pool = malloc(sizehint)) == NULL) { + free(st); + return (NULL); + } + + for (n = 0; n < nbuckets; n++) + SLIST_INIT(&st->st_buckets[n]); + + st->st_len = 0; + st->st_nbuckets = nbuckets; + st->st_string_pool_size = sizehint; + *st->st_string_pool = '\0'; + ELFTC_STRING_TABLE_UPDATE_LENGTH(st, 1); + + return (st); +} + +void +elftc_string_table_destroy(Elftc_String_Table *st) +{ + int n; + struct _Elftc_String_Table_Entry *s, *t; + + for (n = 0; n < st->st_nbuckets; n++) + SLIST_FOREACH_SAFE(s, &st->st_buckets[n], ste_next, t) + free(s); + free(st->st_string_pool); + free(st); + + return; +} + +Elftc_String_Table * +elftc_string_table_from_section(Elf_Scn *scn, int sizehint) +{ + int len; + Elf_Data *d; + GElf_Shdr sh; + const char *s, *end; + Elftc_String_Table *st; + + /* Verify the type of the section passed in. */ + if (gelf_getshdr(scn, &sh) == NULL || + sh.sh_type != SHT_STRTAB) { + errno = EINVAL; + return (NULL); + } + + if ((d = elf_getdata(scn, NULL)) == NULL || + d->d_size == 0) { + errno = EINVAL; + return (NULL); + } + + if ((st = elftc_string_table_create(sizehint)) == NULL) + return (NULL); + + s = d->d_buf; + + /* + * Verify that the first byte of the data buffer is '\0'. + */ + if (*s != '\0') { + errno = EINVAL; + goto fail; + } + + end = s + d->d_size; + + /* + * Skip the first '\0' and insert the strings in the buffer, + * in order. + */ + for (s += 1; s < end; s += len) { + if (elftc_string_table_insert(st, s) == 0) + goto fail; + + len = strlen(s) + 1; /* Include space for the trailing NUL. */ + } + + return (st); + +fail: + if (st) + (void) elftc_string_table_destroy(st); + + return (NULL); +} + +const char * +elftc_string_table_image(Elftc_String_Table *st, size_t *size) +{ + char *r, *s, *end; + struct _Elftc_String_Table_Entry *ste; + struct _Elftc_String_Table_Bucket *head; + int copied, hashindex, offset, length, newsize; + + /* + * For the common case of a string table has not seen + * a string deletion, we can just export the current + * pool. + */ + if ((st->st_len & ELFTC_STRING_TABLE_COMPACTION_FLAG) == 0) { + if (size) + *size = ELFTC_STRING_TABLE_LENGTH(st); + return (st->st_string_pool); + } + + /* + * Otherwise, compact the string table in-place. + */ + assert(*st->st_string_pool == '\0'); + + newsize = 1; + end = st->st_string_pool + ELFTC_STRING_TABLE_LENGTH(st); + + for (r = s = st->st_string_pool + 1; + s < end; + s += length, r += copied) { + + copied = 0; + length = strlen(s) + 1; + + ste = elftc_string_table_find_hash_entry(st, s, + &hashindex); + head = &st->st_buckets[hashindex]; + + assert(ste != NULL); + + /* Ignore deleted strings. */ + if (ste->ste_idx < 0) { + SLIST_REMOVE(head, ste, _Elftc_String_Table_Entry, + ste_next); + free(ste); + continue; + } + + /* Move 'live' strings up. */ + offset = newsize; + newsize += length; + copied = length; + + if (r == s) /* Nothing removed yet. */ + continue; + + memmove(r, s, copied); + + /* Update the index for this entry. */ + ste->ste_idx = offset; + } + + ELFTC_STRING_TABLE_CLEAR_COMPACTION_FLAG(st); + ELFTC_STRING_TABLE_UPDATE_LENGTH(st, newsize); + + if (size) + *size = newsize; + + return (st->st_string_pool); +} + +size_t +elftc_string_table_insert(Elftc_String_Table *st, const char *string) +{ + int hashindex, idx; + struct _Elftc_String_Table_Entry *ste; + + hashindex = 0; + + ste = elftc_string_table_find_hash_entry(st, string, &hashindex); + + assert(hashindex >= 0 && hashindex < st->st_nbuckets); + + if (ste == NULL) { + if ((ste = malloc(sizeof(*ste))) == NULL) + return (0); + if ((ste->ste_idx = elftc_string_table_add_to_pool(st, + string)) == 0) { + free(ste); + return (0); + } + + SLIST_INSERT_HEAD(&st->st_buckets[hashindex], ste, ste_next); + } + + idx = ste->ste_idx; + if (idx < 0) /* Undelete. */ + ste->ste_idx = idx = (- idx); + + return (idx); +} + +size_t +elftc_string_table_lookup(Elftc_String_Table *st, const char *string) +{ + int hashindex, idx; + struct _Elftc_String_Table_Entry *ste; + + ste = elftc_string_table_find_hash_entry(st, string, &hashindex); + + assert(hashindex >= 0 && hashindex < st->st_nbuckets); + + if (ste == NULL || (idx = ste->ste_idx) < 0) + return (0); + + return (idx); +} + +int +elftc_string_table_remove(Elftc_String_Table *st, const char *string) +{ + int idx; + struct _Elftc_String_Table_Entry *ste; + + ste = elftc_string_table_find_hash_entry(st, string, NULL); + + if (ste == NULL || (idx = ste->ste_idx) < 0) + return (ELFTC_FAILURE); + + assert(idx > 0 && idx < (int) ELFTC_STRING_TABLE_LENGTH(st)); + + ste->ste_idx = (- idx); + + ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st); + + return (ELFTC_SUCCESS); +} + +const char * +elftc_string_table_to_string(Elftc_String_Table *st, size_t offset) +{ + const char *s; + + s = st->st_string_pool + offset; + + /* + * Check for: + * - An offset value within pool bounds. + * - A non-NUL byte at the specified offset. + * - The end of the prior string at offset - 1. + */ + if (offset == 0 || offset >= ELFTC_STRING_TABLE_LENGTH(st) || + *s == '\0' || *(s - 1) != '\0') { + errno = EINVAL; + return (NULL); + } + + return (s); +} diff --git a/contrib/elftoolchain/libelftc/elftc_string_table_create.3 b/contrib/elftoolchain/libelftc/elftc_string_table_create.3 new file mode 100644 index 000000000000..e11e73cc4a51 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_string_table_create.3 @@ -0,0 +1,227 @@ +.\" Copyright (c) 2012-2013 Joseph Koshy. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_string_table_create.3 2866 2013-01-06 03:20:14Z jkoshy $ +.\" +.Dd January 5, 2013 +.Os +.Dt ELFTC_STRING_TABLE_CREATE 3 +.Sh NAME +.Nm elftc_string_table_create , +.Nm elftc_string_table_destroy , +.Nm elftc_string_table_from_section , +.Nm elftc_string_table_image , +.Nm elftc_string_table_insert , +.Nm elftc_string_table_lookup , +.Nm elftc_string_table_remove , +.Nm elftc_string_table_to_string +.Nd convenience routines for handling ELF string tables +.Sh SYNOPSIS +.In libelftc.h +.Ft "Elftc_String_Table *" +.Fn elftc_string_table_create "int sizehint" +.Ft int +.Fn elftc_string_table_destroy "Elftc_String_Table *table" +.Ft "Elftc_String_Table *" +.Fn elftc_string_table_from_section "Elf_Scn *scn" "int sizehint" +.Ft "const char *" +.Fo elftc_string_table_image +.Fa "Elftc_String_Table *table" +.Fa "size_t *size" +.Fc +.Ft size_t +.Fo elftc_string_table_insert +.Fa "Elftc_String_Table *table" +.Fa "const char *string" +.Fc +.Ft size_t +.Fo elftc_string_table_lookup +.Fa "Elftc_String_Table *table" +.Fa "const char *string" +.Fc +.Ft int +.Fo elftc_string_table_remove +.Fa "Elftc_String_Table *table" +.Fa "const char *string" +.Fc +.Ft "const char *" +.Fo elftc_string_table_to_string +.Fa "Elftc_String_Table *table" +.Fa "size_t offset" +.Fc +.Sh DESCRIPTION +This manual page documents convenience routines for handling ELF +string tables. +.Pp +Function +.Fn elftc_string_table_create +creates a new, empty string table. +The argument +.Ar sizehint +provides a hint about the expected number of bytes of string data in +the table. +If the argument +.Ar sizehint +is zero, an implementation-defined default will be used instead. +.Pp +Function +.Fn elftc_string_table_destroy +destroys the previously allocated string table specified by +argument +.Ar table , +and frees the internal resources allocated for it. +.Pp +Function +.Fn elftc_string_table_from_section +creates a new string table and initializes it based on the +contents of the section specified by argument +.Ar scn . +This section must be of type +.Dv SHT_STRTAB . +The argument +.Ar sizehint +provides a hint about expected number of bytes of string data in the +table. +If the value of +.Ar sizehint +is zero, an implementation-default will be used instead. +.Pp +Function +.Fn elftc_string_table_image +returns a pointer to the ELF representation of the contents of the +string table specified by argument +.Ar table . +If argument +.Ar size +is not NULL, the size of the ELF representation of the string table is +stored in the location pointed to by argument +.Ar size . +The function +.Fn elftc_string_table_image +will compact the string table if the table contains deleted strings. +The string offsets returned by prior calls to +.Fn elftc_string_table_insert +and +.Fn elftc_string_table_lookup +should be treated as invalid after a call to this function. +.Pp +Function +.Fn elftc_string_table_insert +inserts the NUL-terminated string pointed to by argument +.Ar string +into the string table specified by argument +.Ar table , +and returns an offset value usable in ELF data structures. +Multiple insertions of the same content will return the same offset. +The offset returned will remain valid until the next call to +.Fn elftc_string_table_image . +.Pp +Function +.Fn elftc_string_table_lookup +looks up the string referenced by argument +.Ar string +in the string table specified by argument +.Ar table , +and if found, returns the offset associated with the string. +The returned offset will be valid till the next call to function +.Fn elftc_string_table_image . +.Pp +Function +.Fn elftc_string_table_remove +removes the string pointed by argument +.Ar string +from the string table referenced by argument +.Ar table , +if it is present in the string table. +.Pp +Function +.Fn elftc_string_table_to_string +returns a pointer to the NUL-terminated string residing at argument +.Ar offset +in the string table specified by argument +.Ar table . +The value of argument +.Ar offset +should be one returned by a prior call to +.Fn elftc_string_table_insert +or +.Fn elftc_string_table_lookup . +The returned pointer will remain valid until the next call to +.Fn elftc_string_table_insert +or +.Fn elftc_string_table_image . +.Ss Memory Management +The +.Lb libelftc +library manages its own memory allocations. +The application should not free the pointers returned by the string +table functions. +.El +.Sh IMPLEMENTATION NOTES +The current implementation is optimized for the case where strings are +added to a string table, but rarely removed from it. +.Pp +The functions +.Fn elftc_string_table_insert , +.Fn elftc_string_table_lookup , +.Fn elftc_string_table_remove +and +.Fn elftc_string_table_to_string +have O(1) asymptotic behavior. +The function +.Fn elftc_string_table_image +can have O(size) asymptotic behavior, where +.Ar size +denotes the size of the string table. +.Sh RETURN VALUES +Functions +.Fn elftc_string_table_create +and +.Fn elftc_string_table_from_section +return a valid pointer to an opaque structure of type +.Vt Elftc_String_Table +on success, or NULL in case of an error. +.Pp +The function +.Fn elftc_string_table_image +returns a pointer to an in-memory representation of an ELF string +table on success, or NULL in case of an error. +.Pp +Functions +.Fn elftc_string_table_insert +and +.Fn elftc_string_table_lookup +return a non-zero offset on success, or zero in case of an error. +.Pp +Function +.Fn elftc_string_table_remove +returns a positive value on success, or zero in case of an error. +.Pp +Function +.Fn elftc_string_table_to_string +returns a valid pointer on success, or NULL in case of an error. +.Sh SEE ALSO +.Xr dwarf 3 , +.Xr elf 3 , +.Xr elftc 3 diff --git a/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 b/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 new file mode 100644 index 000000000000..3ff2c3530201 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 @@ -0,0 +1,529 @@ +.\" Copyright (c) 2012 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_symbol_table_create.3 2825 2012-12-29 14:25:33Z jkoshy $ +.\" +.Dd December 29, 2012 +.Os +.Dt ELFTC_SYMBOL_TABLE_CREATE 3 +.Sh NAME +.Nm elftc_elf_symbol_table_from_section , +.Nm elftc_symbol_table_count , +.Nm elftc_symbol_table_create , +.Nm elftc_symbol_table_create_nested , +.Nm elftc_symbol_table_delete_name , +.Nm elftc_symbol_table_delete_entry , +.Nm elftc_symbol_table_destroy , +.Nm elftc_symbol_table_insert , +.Nm elftc_symbol_table_iterate , +.Nm elftc_symbol_table_lookup , +.Nm elftc_symbol_table_lookup_value , +.Nm elftc_symbol_table_replace , +.Nm elftc_symbol_table_sort , +.Nm elftc_symbol_table_step +.Nd symbol table management routines +.Sh SYNOPSIS +.In libelftc.h +.Bd -literal +typedef struct _Elftc_Symbol_Table Elftc_Symbol_Table; + +typedef struct _Elftc_Symbol { + ... library private fields ... + const char *sym_name; + uintptr_t sym_value; +} Elftc_Symbol; +.Ed +.Ft size_t +.Fn elftc_symbol_table_count "Elftc_Symbol_Table *table" +.Ft "Elftc_Symbol_Table *" +.Fo elftc_symbol_table_create +.Fa "size_t entrysize" +.Fa "int sizehint" +.Fc +.Ft "Elftc_Symbol_Table *" +.Fo elftc_symbol_table_create_nested +.Fa "Elftc_Symbol_Table *table" +.Fa "int sizehint" +.Fc +.Ft int +.Fo elftc_symbol_table_delete_name +.Fa "Elftc_Symbol_Table *table" +.Fa "const char *name" +.Fc +.Ft int +.Fo elftc_symbol_table_delete_entry +.Fa "Elftc_Symbol_Table *table" +.Fa "Elftc_Symbol *entry" +.Fc +.Ft int +.Fn elftc_symbol_table_destroy "Elftc_Symbol_Table *table" +.Ft "Elftc_Symbol *entry" +.Fo elftc_symbol_table_insert +.Fa "Elftc_Symbol_Table *table" +.Fa "const char *symbolname" +.Fa "int *status" +.Fc +.Ft int +.Fo elftc_symbol_table_iterate +.Fa "Elftc_Symbol_Table *table" +.Fa "int (*iterfn)(Elftc_Symbol *entry, void *cookie)" +.Fa "void *cookie" +.Fc +.Ft "Elftc_Symbol *" +.Fo elftc_symbol_table_lookup +.Fa "Elftc_Symbol_Table *table" +.Fa "const char *symbolname" +.Fc +.Ft "Elftc_Elf_Symbol *" +.Fo elftc_symbol_table_lookup_value +.Fa "Elftc_Symbol_Table *table" +.Fa "uintptr_t value" +.Fa "int searchflags" +.Fc +.Ft int +.Fo elftc_symbol_table_replace +.Fa "Elftc_Symbol_Table *table" +.Fa "Elftc_Symbol *sym1" +.Fa "Elftc_Symbol *sym2" +.Fc +.Ft int +.Fo elftc_symbol_table_sort +.Fa "Elftc_Symbol_Table *table" +.Fa "int (*cmpfn)(Elftc_Symbol *s1, Elftc_Symbol *s2)" +.Fc +.Ft "Elftc_Symbol *" +.Fo elftc_symbol_table_step +.Fa "Elftc_Symbol_Table *table" +.Fa "Elftc_Symbol *cursym" +.Fa "int direction" +.Fc +.Bd -literal +typedef struct _Elftc_Elf_Symbol { + ... library private fields ... + const char *sym_name; + Gelf_Sym sym_elf; +} Elftc_Elf_Symbol; +.Ed +.Ft "Elftc_Symbol_Table *" +.Fo elftc_elf_symbol_table_from_section +.Fa "Elf_Scn *symscn" +.Fa "Elf_Scn *strscn" +.Fc +.Sh DESCRIPTION +This manual page documents convenience routines for handling symbol +tables. +Two flavors of symbol tables are supported: +.Bl -bullet -compact +.It +.Dq Regular +symbol tables supporting insertion, deletion and lookup of entries by +name or by value, sorting of entries, and stepping through entries in +the table's current traversal order. +.It +.Dq ELF-centric +symbol tables support additional operations for conversions to and +from the symbol table format understood by +.Lb libelf . +.El +The default traversal order for a symbol table is the order in which +entries were inserted into it. +This traversal order may be changed using function +.Fn elftc_symbol_table_sort . +.Ss Operations on Regular Symbol Tables +Regular symbol tables use symbols that are subtypes of +.Vt Elftc_Symbol , +as described in the section +.Sx "Structure of a Symbol Table Entry" +below. +.Pp +Function +.Fn elftc_symbol_table_count +returns the number of entries currently in the symbol table. +.Pp +Function +.Fn elftc_symbol_table_create +creates a new, empty symbol table. +The argument +.Ar entrysize +specifies the size of each symbol table entry, as described +in the section +.Sx "Structure of a Symbol Table Entry" +below. +The argument +.Ar sizehint +specifies the expected number of symbol table entries. +If +.Ar sizehint +is zero, an implementation-defined default will be used. +.Pp +Function +.Fn elftc_symbol_table_create_nested +creates a symbol table whose search scope nests inside that of a +parent symbol table. +The argument +.Ar parent +specifies the parent symbol table to nest under. +The argument +.Ar sizehint +specifies the expected number of symbol table entries. +If +.Ar sizehint +is zero, an implementation-defined default will be used instead. +.Pp +The function +.Fn elftc_symbol_table_delete_name +removes the symbol entry named by the argument +.Ar name +from the symbol table specified by argument +.Ar table , +according to the rules described in section +.Sx "Symbol Search Rules" . +.Pp +The function +.Fn elftc_symbol_table_delete_entry +removes the symbol table entry specified by argument +.Ar entry +from the symbol table specified by argument +.Ar table . +.Pp +Function +.Fn elftc_symbol_table_destroy +is used to destroy a symbol table and free up its internal +resources. +.Pp +The function +.Fn elftc_symbol_table_insert +inserts a symbol entry for the name specified by argument +.Ar symbolname +into the symbol table specified by argument +.Ar table , +returning a pointer to a symbol table entry. +The argument +.Ar status +should point to a location that will be updated with one of +the following values: +.Bl -tag -width indent -compact -offset indent +.It Dv ELFTC_INSERT_ERROR +An error occured during insertion of the symbol. +.It Dv ELFTC_INSERT_EXISTING +The name in argument +.Ar symbolname +was already in the symbol table, and a pointer to the existing +symbol table entry is being returned. +.It Dv ELFTC_INSERT_NEW +A new symbol table entry was allocated for the symbol name +in +.Ar symbolname . +The application will need to initialize the application-specific +fields of the symbol table entry. +.El +Insertion obeys the scoping rules described in section +.Sx "Symbol Search Rules" . +.Pp +The function +.Fn elftc_symbol_table_iterate +iterates over the symbol table specifed by argument +.Ar table , +applying the function pointed to by argument +.Ar iterfn +to each symbol table entry. +The return value from the function +.Ar iterfn +controls progress of the iteration: +.Bl -tag -width indent -compact -offset indent +.It Dv ELFTC_ITERATE_ABORT +Terminates the iteration. +.It Dv ELFTC_ITERATE_CONTINUE +Iteration will continue on to the next element in the symbol table. +.El +Argument +.Ar cookie +will be passed to each invocation of +.Ar iterfn , +and may be used to track persistent state. +The ordering of symbol table entries presented to function +.Ar iterfn +is not defined. +The behavior of the iteration is undefined if +.Ar iterfn +adds or deletes symbol entries from a symbol table that currently +being iterated through. +.Pp +Function +.Fn elftc_symbol_table_lookup +returns the symbol entry corresponding to the name of the symbol +in argument +.Ar symbolname . +.Pp +Function +.Fn elftc_symbol_table_lookup_value +returns the symbol entry that has a +.Va sym_value +field that is closest to the value specified in argument +.Ar value . +The argument +.Ar table +should point to a symbol table, that has been sorted +by a prior call to +.Fn elftc_symbol_table_sort . +The argument +.Ar searchflags +can be a combination of the following flags: +.Bl -tag -width indent -compact -offset indent +.It Dv ELFTC_SEARCH_FORWARD +Find the symbol entry with the next higher value in its +.Va sym_value +field. +.It Dv ELFTC_SEARCH_BACKWARD +Find the symbol entry with next lower value in its +.Va sym_value +field. +.El +If both +.Dv ELFTC_SEARCH_FORWARD +and +.Dv ELFTC_SEARCH_BACKWARD +are specified, then this function will return the symbol that is +closest to the argument +.Ar value . +.Pp +Function +.Fn elftc_symbol_table_replace +moves the symbol table entry pointed to by argument +.Ar sym2 +into the traversal position for the entry pointed to by +.Ar sym1 , +and implicitly deletes the entry pointed to by argument +.Ar sym1 . +Argument +.Ar table +should point to a valid symbol table. +.Pp +Function +.Fn elftc_symbol_table_sort +is used to define an ordering of symbol entries in a symbol +table. +This ordering will be associated with the symbol table till the next +call to function +.Fn elftc_symbol_table_insert , +.Fn elftc_symbol_table_delete_name +or +.Fn elftc_symbol_table_delete_entry . +The argument +.Ar cmpfn +should point to a function that compares two symbol entries pointed +to by +.Ar s1 +and +.Ar s2 +and returns -1, 0, or 1, depending whether +.Ar s1 +is less, equal to, or greater than +.Ar s2 +respectively. +.Pp +Function +.Fn elftc_symbol_table_step +is used to step to the next symbol in a sorted symbol table. +Argument +.Ar table +should point to a symbol table. +The argument +.Ar cursym +specifies the current symbol. +The argument +.Ar direction +specifies the direction to step: +.Bl -tag -width indent -compact -offset ident +.It Dv ELFTC_STEP_NEXT +Return the symbol which follows the argument +.Ar cursym +in the current traversal order. +If argument +.Ar cursym +is NULL, return the first symbol in the current +traversal order. +.It Dv ELFTC_STEP_PREVIOUS +Return the symbol which precedes the argument +.Ar cursym +in the current traversal order. +If argument +.Ar cursym +is NULL, return the last symbol in the current +traversal order. +.El +.Ss Operations on ELF-centric symbol tables +ELF-centric symbol tables use symbols that are subtypes of +.Vt Elftc_Elf_Symbol , +as described in the section +.Sx "Structure of a Symbol Table Entry" +below. +.Pp +In addition to the operations on regular symbol tables listed above, +these symbol tables may be used with the following additional +functions. +.Pp +The function +.Fn elftc_elf_symbol_table_from_section +builds a symbol table from the contents of an ELF section. +The argument +.Ar symscn +should reference an ELF section of type +.Dv SHT_SYMTAB +or +.Dv SHT_DYNSYM . +The argument +.Ar strscn +should reference an ELF section of type +.Dv SHT_STRTAB +containing the string table associated wit section +.Ar symscn . +.Ss Structure of a Symbol Table Entry +The symbol tables managed by +.Lb libelftc +are collections of symbol table entries. +Each entry should be a subtype of one of the +.Vt Elftc_Symbol +or +.Vt Elftc_Elf_Symbol +types. +In other words, each entry should have an +.Vt Elftc_Symbol +or +.Vt Elftc_Elf_Symbol +structure as its first member, before any application specific +fields. +For example: +.Bd -literal -offset indent +struct _MySymbol { + Elftc_Symbol sym_base; + ... other application-specific fields ... +}; +.Ed +.Pp +The size of the combined entry is indicated to the library +at the time of creating a new symbol table. +Applications may then cast the returned pointers from these +routines to the appropriate type: +.Bd -literal -offset indent +struct _MySymbol *mysym; + +mysym = (struct _MySymbol *) elftc_symbol_table_lookup(table, + name); +.Ed +.Pp +The +.Vt Elftc_Symbol +type has two public fields: +.Bl -tag -width ".Va sym_value" -compact -offset indent +.It Va sym_name +Points to a NUL-terminated string containing the symbol's name. +The application should not change the value of this field. +.It Va sym_value +The value associated with this symbol. +This field is entirely under the application's control. +.El +.Pp +The +.Vt Elftc_Elf_Symbol +type has two public fields: +.Bl -tag -width ".Va sym_value" -compact -offset indent +.It Va sym_name +Points to a NUL-terminated string containing the symbol's name. +The application should not change the value of this field. +.It Va sym_elf +A structure of type +.Vt Gelf_Sym +containing ELF symbol information. +This field is entirely under the application's control. +.El +.Ss Symbol Search Rules +During lookups, symbols are looked up first in the symbol table passed in +to the +.Fn elftc_symbol_table_lookup +function. +If the specified symbol is not found, and if the symbol table has a +parent, then the search continues recursively up the chain of parent +symbol tables till either a matching symbol is found or till there are +no more parent symbol tables to search in. +.Pp +Insertions and deletion only work on the specified symbol table and +do not recurse into parent symbol tables. +.Ss Memory Management +The +.Lb libelftc +manages its memory allocations. +Applications should not free the pointers returned by the +API documented in this manual page. +.Sh RETURN VALUES +Function +.Fn elftc_symbol_table_count +returns a count of the number of symbol table entries as an unsigned +value. +.Pp +Functions +.Fn elftc_symbol_table_create , +.Fn elftc_symbol_table_create_nested +and +.Fn elftc_symbol_table_from_section +return a pointer to an opaque structure of type +.Vt Elftc_Symbol_Table +on success, or return NULL in case of an error. +.Pp +Functions +.Fn elftc_symbol_table_delete_name , +.Fn elftc_symbol_table_delete_name +.Fn elftc_symbol_table_destroy , +.Fn elftc_symbol_table_replace +and +.Fn elftc_symbol_table_sort +return a non-zero value on success, or return zero in case of an error. +.Pp +Functions +.Fn elftc_symbol_table_insert , +.Fn elftc_symbol_table_lookup +and +.Fn elftc_symbol_table_lookup_value +return a pointer to a structure that is a subtype of +.Vt Elftc_Symbol +on success, or return NULL in case of an error. +.Pp +The function +.Fn elftc_symbol_table_step +return a pointer to a structure that is a subtype of +.Vt Elftc_Symbol +on success. +The function returns NULL if there are no more elements in the +specified traversal direction. +.Pp +The function +.Fn elftc_symbol_table_iterate +returns +.Dv ELFTC_ITERATE_SUCCESS +if the symbol table was successfully traversed, or +.Dv ELFTC_ITERATE_ABORT +in case the iteration function aborted the traversal. +.Sh SEE ALSO +.Xr dwarf 3 , +.Xr elf 3 , +.Xr elftc 3 diff --git a/contrib/elftoolchain/libelftc/elftc_version.3 b/contrib/elftoolchain/libelftc/elftc_version.3 new file mode 100644 index 000000000000..f7018a50d087 --- /dev/null +++ b/contrib/elftoolchain/libelftc/elftc_version.3 @@ -0,0 +1,79 @@ +.\" Copyright (c) 2011,2012 Joseph Koshy. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" This software is provided by Joseph Koshy ``as is'' and +.\" any express or implied warranties, including, but not limited to, the +.\" implied warranties of merchantability and fitness for a particular purpose +.\" are disclaimed. in no event shall Joseph Koshy be liable +.\" for any direct, indirect, incidental, special, exemplary, or consequential +.\" damages (including, but not limited to, procurement of substitute goods +.\" or services; loss of use, data, or profits; or business interruption) +.\" however caused and on any theory of liability, whether in contract, strict +.\" liability, or tort (including negligence or otherwise) arising in any way +.\" out of the use of this software, even if advised of the possibility of +.\" such damage. +.\" +.\" $Id: elftc_version.3 2828 2012-12-30 04:41:27Z jkoshy $ +.\" +.Dd December 30, 2012 +.Os +.Dt ELFTC_VERSION 3 +.Sh NAME +.Nm elftc_version +.Nd return a project-wide version identifier string +.Sh LIBRARY +.Lb libelftc +.Sh SYNOPSIS +.In libelftc.h +.Ft const char * +.Fn elftc_version void +.Sh DESCRIPTION +Function +.Fn elftc_version +returns a project-wide identifier string that encodes the source +revision of the project source tree. +.Pp +The returned identifier has four space-separated fields: +.Bl -tag -width ".Em Project Branch" +.It Em "Project-Name" +This is always +.Dq elftoolchain . +.It Em "Project-Branch" +The branch name for the project source tree. +.It Em "Build-OS" +The operating system that the tool chain was compiled for. +.It Em "Version-Number" +A tree-wide version number extracted from the version control +system in use. +.El +.Sh RETURN VALUE +Function +.Fn elftc_program_version +returns a pointer to an internal character buffer. +.Sh EXAMPLES +To retrieve and print the current toolchain version identifier, use: +.Bd -literal -offset indent +#include +#include + +(void) printf("%s\en", elftc_version()); +.Ed +.Pp +On the HEAD branch of the project's sources, when checked out using +Subversion and compiled on a NetBSD host, this would print: +.D1 Dq elftoolchain HEAD NetBSD svn: Ns Em REVINFO +where +.Em REVINFO +would be the current revision information for the project source tree. +.Sh ERRORS +Function +.Fn elftc_program_version +always succeeds. diff --git a/contrib/elftoolchain/libelftc/libelftc.h b/contrib/elftoolchain/libelftc/libelftc.h new file mode 100644 index 000000000000..aa6b0b6ffe1e --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc.h @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $ + * $Id: libelftc.h 2863 2013-01-06 03:18:32Z jkoshy $ + */ + +#ifndef _LIBELFTC_H_ +#define _LIBELFTC_H_ + +#include + +#include + +typedef struct _Elftc_Bfd_Target Elftc_Bfd_Target; +typedef struct _Elftc_String_Table Elftc_String_Table; + +/* Target types. */ +typedef enum { + ETF_NONE, + ETF_ELF, + ETF_BINARY, + ETF_SREC, + ETF_IHEX +} Elftc_Bfd_Target_Flavor; + +/* + * Demangler flags. + */ + +/* Name mangling style. */ +#define ELFTC_DEM_UNKNOWN 0x00000000U /* Not specified. */ +#define ELFTC_DEM_ARM 0x00000001U /* C++ Ann. Ref. Manual. */ +#define ELFTC_DEM_GNU2 0x00000002U /* GNU version 2. */ +#define ELFTC_DEM_GNU3 0x00000004U /* GNU version 3. */ + +/* Demangling behaviour control. */ +#define ELFTC_DEM_NOPARAM 0x00010000U + +__BEGIN_DECLS +Elftc_Bfd_Target *elftc_bfd_find_target(const char *_tgt_name); +Elftc_Bfd_Target_Flavor elftc_bfd_target_flavor(Elftc_Bfd_Target *_tgt); +unsigned int elftc_bfd_target_byteorder(Elftc_Bfd_Target *_tgt); +unsigned int elftc_bfd_target_class(Elftc_Bfd_Target *_tgt); +unsigned int elftc_bfd_target_machine(Elftc_Bfd_Target *_tgt); +int elftc_copyfile(int _srcfd, int _dstfd); +int elftc_demangle(const char *_mangledname, char *_buffer, + size_t _bufsize, unsigned int _flags); +int elftc_set_timestamps(const char *_filename, struct stat *_sb); +Elftc_String_Table *elftc_string_table_create(int _hint); +void elftc_string_table_destroy(Elftc_String_Table *_table); +Elftc_String_Table *elftc_string_table_from_section(Elf_Scn *_scn, + int _hint); +const char *elftc_string_table_image(Elftc_String_Table *_table, + size_t *_sz); +size_t elftc_string_table_insert(Elftc_String_Table *_table, + const char *_string); +size_t elftc_string_table_lookup(Elftc_String_Table *_table, + const char *_string); +int elftc_string_table_remove(Elftc_String_Table *_table, + const char *_string); +const char *elftc_string_table_to_string(Elftc_String_Table *_table, + size_t offset); +const char *elftc_version(void); +__END_DECLS + +#endif /* _LIBELFTC_H_ */ diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c new file mode 100644 index 000000000000..31c89b74f14a --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c @@ -0,0 +1,383 @@ +/*- + * Copyright (c) 2008,2009 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $"); + +struct _Elftc_Bfd_Target _libelftc_targets[] = { + + { + .bt_name = "binary", + .bt_type = ETF_BINARY, + }, + + { + .bt_name = "elf32-avr", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_AVR, + }, + + { + .bt_name = "elf32-big", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + }, + + { + .bt_name = "elf32-bigarm", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_ARM, + }, + + { + .bt_name = "elf32-bigmips", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_MIPS, + }, + + { + .bt_name = "elf32-i386", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_386, + }, + + { + .bt_name = "elf32-i386-freebsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_386, + .bt_osabi = ELFOSABI_FREEBSD, + }, + + { + .bt_name = "elf32-ia64-big", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_IA_64, + }, + + { + .bt_name = "elf32-little", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + }, + + { + .bt_name = "elf32-littlearm", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_ARM, + }, + + { + .bt_name = "elf32-littlemips", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_MIPS, + }, + + { + .bt_name = "elf32-powerpc", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_PPC, + }, + + { + .bt_name = "elf32-powerpcle", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_PPC, + }, + + { + .bt_name = "elf32-sh", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + }, + + { + .bt_name = "elf32-shl", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + }, + + { + .bt_name = "elf32-sh-nbsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_NETBSD, + }, + + { + .bt_name = "elf32-shl-nbsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_NETBSD, + }, + + { + .bt_name = "elf32-shbig-linux", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_LINUX, + }, + + { + .bt_name = "elf32-sh-linux", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_LINUX, + }, + + { + .bt_name = "elf32-sparc", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS32, + .bt_machine = EM_SPARC, + }, + + { + .bt_name = "elf64-alpha", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_ALPHA, + }, + + { + .bt_name = "elf64-alpha-freebsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_ALPHA, + .bt_osabi = ELFOSABI_FREEBSD + }, + + { + .bt_name = "elf64-big", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + }, + + { + .bt_name = "elf64-bigmips", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_MIPS, + }, + + { + .bt_name = "elf64-ia64-big", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_IA_64, + }, + + { + .bt_name = "elf64-ia64-little", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_IA_64, + }, + + { + .bt_name = "elf64-little", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + }, + + { + .bt_name = "elf64-littlemips", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_MIPS, + }, + + { + .bt_name = "elf64-powerpc", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_PPC64, + }, + + { + .bt_name = "elf64-powerpcle", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_PPC64, + }, + + { + .bt_name = "elf64-sh64", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + }, + + { + .bt_name = "elf64-sh64l", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + }, + + { + .bt_name = "elf64-sh64-nbsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_NETBSD, + }, + + { + .bt_name = "elf64-sh64l-nbsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_NETBSD, + }, + + { + .bt_name = "elf64-sh64big-linux", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_LINUX, + }, + + { + .bt_name = "elf64-sh64-linux", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SH, + .bt_osabi = ELFOSABI_LINUX, + }, + + { + .bt_name = "elf64-sparc", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SPARCV9, + }, + + { + .bt_name = "elf64-sparc-freebsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2MSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_SPARCV9, + .bt_osabi = ELFOSABI_FREEBSD + }, + + { + .bt_name = "elf64-x86-64", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_X86_64, + }, + + { + .bt_name = "elf64-x86-64-freebsd", + .bt_type = ETF_ELF, + .bt_byteorder = ELFDATA2LSB, + .bt_elfclass = ELFCLASS64, + .bt_machine = EM_X86_64, + .bt_osabi = ELFOSABI_FREEBSD + }, + + { + .bt_name = "ihex", + .bt_type = ETF_IHEX, + }, + + { + .bt_name = "srec", + .bt_type = ETF_SREC, + }, + + { + .bt_name = "symbolsrec", + .bt_type = ETF_SREC, + }, + + { + .bt_name = NULL, + .bt_type = ETF_NONE, + }, +}; diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_arm.c b/contrib/elftoolchain/libelftc/libelftc_dem_arm.c new file mode 100644 index 000000000000..e850b8b5724d --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_dem_arm.c @@ -0,0 +1,1227 @@ +/*- + * Copyright (c) 2008 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_dem_arm.c 2065 2011-10-26 15:24:47Z jkoshy $"); + +/** + * @file cpp_demangle_arm.c + * @brief Decode function name encoding in ARM. + * + * Function name encoding in "The Annotated C++ Reference Manual". + * + * Ref : "The Annotated C++ Reference Manual", Margaet A.Ellis, + * Bjarne Stroustrup, AT&T Bell Laboratories 1990, pp 122-126. + */ + +enum encode_type { + ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER +}; + +struct cstring { + char *buf; + size_t size; +}; + +struct demangle_data { + bool ptr, ref, cnst, array; + struct cstring array_str; + const char *p; + enum encode_type type; + struct vector_str vec; + struct vector_str arg; +}; + +#define SIMPLE_HASH(x,y) (64 * x + y) +#define CPP_DEMANGLE_ARM_TRY 128 + +static void dest_cstring(struct cstring *); +static void dest_demangle_data(struct demangle_data *); +static bool init_cstring(struct cstring *, size_t); +static bool init_demangle_data(struct demangle_data *); +static bool push_CTDT(const char *, size_t, struct vector_str *); +static bool read_array(struct demangle_data *); +static bool read_class(struct demangle_data *); +static bool read_func(struct demangle_data *); +static bool read_func_name(struct demangle_data *); +static bool read_func_ptr(struct demangle_data *); +static bool read_memptr(struct demangle_data *); +static bool read_op(struct demangle_data *); +static bool read_op_user(struct demangle_data *); +static bool read_qual_name(struct demangle_data *); +static int read_subst(struct demangle_data *); +static int read_subst_iter(struct demangle_data *); +static bool read_type(struct demangle_data *); + +/** + * @brief Decode the input string by the ARM style. + * + * @return New allocated demangled string or NULL if failed. + */ +char * +cpp_demangle_ARM(const char *org) +{ + struct demangle_data d; + size_t arg_begin, arg_len; + unsigned int try; + char *rtn, *arg; + + if (org == NULL) + return (NULL); + + if (init_demangle_data(&d) == false) + return (NULL); + + try = 0; + rtn = NULL; + + d.p = org; + if (read_func_name(&d) == false) + goto clean; + + if (d.type == ENCODE_OP_CT) { + if (push_CTDT("::", 2, &d.vec) == false) + goto clean; + + goto flat; + } + + if (d.type == ENCODE_OP_DT) { + if (push_CTDT("::~", 3, &d.vec) == false) + goto clean; + + goto flat; + } + + if (d.type == ENCODE_OP_USER) + goto flat; + + /* function type */ + if (*d.p != 'F') + goto clean; + ++d.p; + + /* start argument types */ + if (vector_str_push(&d.vec, "(", 1) == false) + goto clean; + + for (;;) { + if (*d.p == 'T') { + const int rtn_subst = read_subst(&d); + + if (rtn_subst == -1) + goto clean; + else if (rtn_subst == 1) + break; + + continue; + } + + if (*d.p == 'N') { + const int rtn_subst_iter = read_subst_iter(&d); + + if (rtn_subst_iter == -1) + goto clean; + else if(rtn_subst_iter == 1) + break; + + continue; + } + + arg_begin = d.vec.size; + + if (read_type(&d) == false) + goto clean; + + if (d.ptr == true) { + if (vector_str_push(&d.vec, "*", 1) == false) + goto clean; + + d.ptr = false; + } + + if (d.ref == true) { + if (vector_str_push(&d.vec, "&", 1) == false) + goto clean; + + d.ref = false; + } + + if (d.cnst == true) { + if (vector_str_push(&d.vec, " const", 6) == false) + goto clean; + + d.cnst = false; + } + + if (d.array == true) { + if (vector_str_push(&d.vec, d.array_str.buf, + d.array_str.size) == false) + goto clean; + + dest_cstring(&d.array_str); + d.array = false; + } + + if (*d.p == '\0') + break; + + if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1, + &arg_len)) == NULL) + goto clean; + + if (vector_str_push(&d.arg, arg, arg_len) == false) + goto clean; + + free(arg); + + if (vector_str_push(&d.vec, ", ", 2) == false) + goto clean; + + if (++try > CPP_DEMANGLE_ARM_TRY) + goto clean; + } + + /* end argument types */ + if (vector_str_push(&d.vec, ")", 1) == false) + goto clean; + +flat: + rtn = vector_str_get_flat(&d.vec, NULL); +clean: + dest_demangle_data(&d); + + return (rtn); +} + +/** + * @brief Test input string is encoded by the ARM style. + * + * @return True if input string is encoded by the ARM style. + */ +bool +is_cpp_mangled_ARM(const char *org) +{ + + if (org == NULL) + return (false); + + return (strstr(org, "__") != NULL); +} + +static void +dest_cstring(struct cstring *s) +{ + + if (s == NULL) + return; + + free(s->buf); + s->buf = NULL; + s->size = 0; +} + +static void +dest_demangle_data(struct demangle_data *d) +{ + + if (d != NULL) { + vector_str_dest(&d->arg); + vector_str_dest(&d->vec); + + dest_cstring(&d->array_str); + } +} + +static bool +init_cstring(struct cstring *s, size_t len) +{ + + if (s == NULL || len <= 1) + return (false); + + if ((s->buf = malloc(sizeof(char) * len)) == NULL) + return (false); + + s->size = len - 1; + + return (true); +} + +static bool +init_demangle_data(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + d->ptr = false; + d->ref = false; + d->cnst = false; + d->array = false; + + d->array_str.buf = NULL; + d->array_str.size = 0; + + d->type = ENCODE_FUNC; + + if (vector_str_init(&d->vec) == false) + return (false); + + if (vector_str_init(&d->arg) == false) { + vector_str_dest(&d->vec); + + return (false); + } + + return (true); +} + +static bool +push_CTDT(const char *s, size_t l, struct vector_str *v) +{ + + if (s == NULL || l == 0 || v == NULL) + return (false); + + if (vector_str_push(v, s, l) == false) + return (false); + + assert(v->size > 1); + if (vector_str_push(v, v->container[v->size - 2], + strlen(v->container[v->size - 2])) == false) + return (false); + + if (vector_str_push(v, "()", 2) == false) + return (false); + + return (true); +} + +static bool +read_array(struct demangle_data *d) +{ + size_t len; + const char *end; + + if (d == NULL || d->p == NULL) + return (false); + + end = d->p; + assert(end != NULL); + + for (;;) { + if (*end == '\0') + return (false); + + if (ELFTC_ISDIGIT(*end) == 0) + break; + + ++end; + } + + if (*end != '_') + return (false); + + len = end - d->p; + assert(len > 0); + + dest_cstring(&d->array_str); + if (init_cstring(&d->array_str, len + 3) == false) + return (false); + + strncpy(d->array_str.buf + 1, d->p, len); + *d->array_str.buf = '['; + *(d->array_str.buf + len + 1) = ']'; + + d->array = true; + d->p = end + 1; + + return (true); +} + +static bool +read_class(struct demangle_data *d) +{ + size_t len; + char *str; + + if (d == NULL) + return (false); + + len = strtol(d->p, &str, 10); + if (len == 0 && (errno == EINVAL || errno == ERANGE)) + return (false); + + assert(len > 0); + assert(str != NULL); + + if (vector_str_push(&d->vec, str, len) == false) + return (false); + + d->p = str + len; + + return (true); +} + +static bool +read_func(struct demangle_data *d) +{ + size_t len; + const char *name; + char *delim; + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + if ((delim = strstr(d->p, "__")) == NULL) + return (false); + + len = delim - d->p; + assert(len != 0); + + name = d->p; + + d->p = delim + 2; + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + if (read_qual_name(d) == false) + return (false); + } else if (ELFTC_ISDIGIT(*d->p)) { + if (read_class(d) == false) + return (false); + + if (vector_str_push(&d->vec, "::", 2) == false) + return (false); + } + + if (vector_str_push(&d->vec, name, len) == false) + return (false); + + return (true); +} + +static bool +read_func_name(struct demangle_data *d) +{ + size_t len; + bool rtn; + char *op_name; + + if (d == NULL) + return (false); + + rtn = false; + op_name = NULL; + + assert(d->p != NULL && "d->p (org str) is NULL"); + + if (*d->p == '_' && *(d->p + 1) == '_') { + d->p += 2; + + d->type = ENCODE_OP; + if (read_op(d) == false) + return (false); + + if (d->type == ENCODE_OP_CT || d->type == ENCODE_OP_DT || + d->type == ENCODE_OP_USER) + return (true); + + /* skip "__" */ + d->p += 2; + + /* assume delimiter is removed */ + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + assert(d->vec.size > 0); + + len = strlen(d->vec.container[d->vec.size - 1]); + if ((op_name = malloc(sizeof(char) * (len + 1))) + == NULL) + return (false); + + snprintf(op_name, len + 1, "%s", + d->vec.container[d->vec.size - 1]); + vector_str_pop(&d->vec); + + if (read_qual_name(d) == false) + goto clean; + + if (vector_str_push(&d->vec, "::", 2) == false) + goto clean; + + if (vector_str_push(&d->vec, op_name, len) == false) + goto clean; + + rtn = true; + } else if (ELFTC_ISDIGIT(*d->p)) { + assert(d->vec.size > 0); + + len = strlen(d->vec.container[d->vec.size - 1]); + if ((op_name = malloc(sizeof(char) * (len + 1))) + == NULL) + return (false); + + snprintf(op_name, len + 1, "%s", + d->vec.container[d->vec.size - 1]); + vector_str_pop(&d->vec); + + if (read_class(d) == false) + goto clean; + + if (vector_str_push(&d->vec, "::", 2) == false) + goto clean; + + if (vector_str_push(&d->vec, op_name, len) == false) + goto clean; + + rtn = true; + } + } else + return (read_func(d)); + +clean: + free(op_name); + + return (rtn); +} + +/* Read function ptr type */ +static bool +read_func_ptr(struct demangle_data *d) +{ + struct demangle_data fptr; + size_t arg_len, rtn_len; + char *arg_type, *rtn_type; + int lim; + + if (d == NULL) + return (false); + + if (init_demangle_data(&fptr) == false) + return (false); + + fptr.p = d->p + 1; + lim = 0; + arg_type = NULL; + rtn_type = NULL; + + for (;;) { + if (read_type(&fptr) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + if (fptr.ptr == true) { + if (vector_str_push(&fptr.vec, "*", 1) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.ptr = false; + } + + if (fptr.ref == true) { + if (vector_str_push(&fptr.vec, "&", 1) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.ref = false; + } + + if (fptr.cnst == true) { + if (vector_str_push(&fptr.vec, " const", 6) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.cnst = false; + } + + if (*fptr.p == '_') + break; + + if (vector_str_push(&fptr.vec, ", ", 2) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + if (++lim > CPP_DEMANGLE_ARM_TRY) { + + dest_demangle_data(&fptr); + + return (false); + } + } + + arg_type = vector_str_get_flat(&fptr.vec, &arg_len); + /* skip '_' */ + d->p = fptr.p + 1; + + dest_demangle_data(&fptr); + + if (init_demangle_data(&fptr) == false) { + free(arg_type); + + return (false); + } + + fptr.p = d->p; + lim = 0; + + if (read_type(&fptr) == false) { + free(arg_type); + dest_demangle_data(&fptr); + + return (false); + } + + rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len); + d->p = fptr.p; + + + dest_demangle_data(&fptr); + + if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) { + free(rtn_type); + free(arg_type); + + return (false); + } + + free(rtn_type); + + if (vector_str_push(&d->vec, " (*)(", 5) == false) { + free(arg_type); + + return (false); + } + + if (vector_str_push(&d->vec, arg_type, arg_len) == false) { + free(arg_type); + + return (false); + } + + free(arg_type); + + return (vector_str_push(&d->vec, ")", 1)); +} + +static bool +read_memptr(struct demangle_data *d) +{ + struct demangle_data mptr; + size_t len; + bool rtn; + char *mptr_str; + + if (d == NULL || d->p == NULL) + return (false); + + if (init_demangle_data(&mptr) == false) + return (false); + + rtn = false; + mptr_str = NULL; + + mptr.p = d->p; + if (*mptr.p == 'Q') { + ++mptr.p; + + if (read_qual_name(&mptr) == false) + goto clean; + } else { + if (read_class(&mptr) == false) + goto clean; + } + + d->p = mptr.p; + + if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL) + goto clean; + + if (vector_str_push(&d->vec, mptr_str, len) == false) + goto clean; + + if (vector_str_push(&d->vec, "::*", 3) == false) + goto clean; + + rtn = true; +clean: + free(mptr_str); + dest_demangle_data(&mptr); + + return (rtn); +} + +static bool +read_op(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + + switch (SIMPLE_HASH(*(d->p), *(d->p+1))) { + case SIMPLE_HASH('m', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator*", 9)); + case SIMPLE_HASH('d', 'v') : + d->p += 2; + return (vector_str_push(&d->vec, "operator/", 9)); + case SIMPLE_HASH('m', 'd') : + d->p += 2; + return (vector_str_push(&d->vec, "operator%", 9)); + case SIMPLE_HASH('p', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator+", 9)); + case SIMPLE_HASH('m', 'i') : + d->p += 2; + return (vector_str_push(&d->vec, "operator-", 9)); + case SIMPLE_HASH('l', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<<", 10)); + case SIMPLE_HASH('r', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>>", 10)); + case SIMPLE_HASH('e', 'q') : + d->p += 2; + return (vector_str_push(&d->vec, "operator==", 10)); + case SIMPLE_HASH('n', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator!=", 10)); + case SIMPLE_HASH('l', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<", 9)); + case SIMPLE_HASH('g', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>", 9)); + case SIMPLE_HASH('l', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<=", 10)); + case SIMPLE_HASH('g', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>=", 10)); + case SIMPLE_HASH('a', 'd') : + d->p += 2; + if (*d->p == 'v') { + ++d->p; + return (vector_str_push(&d->vec, "operator/=", + 10)); + } else + return (vector_str_push(&d->vec, "operator&", 9)); + case SIMPLE_HASH('o', 'r') : + d->p += 2; + return (vector_str_push(&d->vec, "operator|", 9)); + case SIMPLE_HASH('e', 'r') : + d->p += 2; + return (vector_str_push(&d->vec, "operator^", 9)); + case SIMPLE_HASH('a', 'a') : + d->p += 2; + if (*d->p == 'd') { + ++d->p; + return (vector_str_push(&d->vec, "operator&=", + 10)); + } else + return (vector_str_push(&d->vec, "operator&&", + 10)); + case SIMPLE_HASH('o', 'o') : + d->p += 2; + return (vector_str_push(&d->vec, "operator||", 10)); + case SIMPLE_HASH('n', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator!", 9)); + case SIMPLE_HASH('c', 'o') : + d->p += 2; + return (vector_str_push(&d->vec, "operator~", 9)); + case SIMPLE_HASH('p', 'p') : + d->p += 2; + return (vector_str_push(&d->vec, "operator++", 10)); + case SIMPLE_HASH('m', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator--", 10)); + case SIMPLE_HASH('a', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator=", 9)); + case SIMPLE_HASH('r', 'f') : + d->p += 2; + return (vector_str_push(&d->vec, "operator->", 10)); + case SIMPLE_HASH('a', 'p') : + /* apl */ + if (*(d->p + 2) != 'l') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator+=", 10)); + case SIMPLE_HASH('a', 'm') : + d->p += 2; + if (*d->p == 'i') { + ++d->p; + return (vector_str_push(&d->vec, "operator-=", + 10)); + } else if (*d->p == 'u') { + ++d->p; + return (vector_str_push(&d->vec, "operator*=", + 10)); + } else if (*d->p == 'd') { + ++d->p; + return (vector_str_push(&d->vec, "operator%=", + 10)); + } + + return (false); + case SIMPLE_HASH('a', 'l') : + /* als */ + if (*(d->p + 2) != 's') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator<<=", 11)); + case SIMPLE_HASH('a', 'r') : + /* ars */ + if (*(d->p + 2) != 's') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator>>=", 11)); + case SIMPLE_HASH('a', 'o') : + /* aor */ + if (*(d->p + 2) != 'r') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator|=", 10)); + case SIMPLE_HASH('a', 'e') : + /* aer */ + if (*(d->p + 2) != 'r') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator^=", 10)); + case SIMPLE_HASH('c', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator,", 9)); + case SIMPLE_HASH('r', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator->*", 11)); + case SIMPLE_HASH('c', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "()", 2)); + case SIMPLE_HASH('v', 'c') : + d->p += 2; + return (vector_str_push(&d->vec, "[]", 2)); + case SIMPLE_HASH('c', 't') : + d->p += 4; + d->type = ENCODE_OP_CT; + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + return (read_qual_name(d)); + } else if (ELFTC_ISDIGIT(*d->p)) + return (read_class(d)); + + return (false); + case SIMPLE_HASH('d', 't') : + d->p += 4; + d->type = ENCODE_OP_DT; + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + return (read_qual_name(d)); + } else if (ELFTC_ISDIGIT(*d->p)) + return (read_class(d)); + + return (false); + case SIMPLE_HASH('n', 'w') : + d->p += 2; + return (vector_str_push(&d->vec, "operator new()", 14)); + case SIMPLE_HASH('d', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator delete()", + 17)); + case SIMPLE_HASH('o', 'p') : + /* __op__ */ + d->p += 2; + + d->type = ENCODE_OP_USER; + + return (read_op_user(d)); + default : + return (false); + }; +} + +static bool +read_op_user(struct demangle_data *d) +{ + struct demangle_data from, to; + size_t from_len, to_len; + bool rtn; + char *from_str, *to_str; + + if (d == NULL) + return (false); + + if (init_demangle_data(&from) == false) + return (false); + + rtn = false; + from_str = NULL; + to_str = NULL; + if (init_demangle_data(&to) == false) + goto clean; + + to.p = d->p; + if (*to.p == 'Q') { + ++to.p; + + if (read_qual_name(&to) == false) + goto clean; + + /* pop last '::' */ + if (vector_str_pop(&to.vec) == false) + goto clean; + } else { + if (read_class(&to) == false) + goto clean; + + /* skip '__' */ + to.p += 2; + } + + if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL) + goto clean; + + from.p = to.p; + if (*from.p == 'Q') { + ++from.p; + + if (read_qual_name(&from) == false) + goto clean; + + /* pop last '::' */ + if (vector_str_pop(&from.vec) == false) + goto clean; + } else { + if (read_class(&from) == false) + goto clean; + } + + if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL) + goto clean; + + if (vector_str_push(&d->vec, from_str, from_len) == false) + goto clean; + + if (vector_str_push(&d->vec, "::operator ", 11) == false) + return (false); + + if (vector_str_push(&d->vec, to_str, to_len) == false) + goto clean; + + rtn = vector_str_push(&d->vec, "()", 2); +clean: + free(to_str); + free(from_str); + dest_demangle_data(&to); + dest_demangle_data(&from); + + return (rtn); +} + +/* single digit + class names */ +static bool +read_qual_name(struct demangle_data *d) +{ + int i; + char num; + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); + + num = *d->p - 48; + + assert(num > 0); + + ++d->p; + for (i = 0; i < num ; ++i) { + if (read_class(d) == false) + return (false); + + if (vector_str_push(&d->vec, "::", 2) == false) + return (false); + } + + if (*d->p != '\0') + d->p = d->p + 2; + + return (true); +} + +/* Return -1 at fail, 0 at success, and 1 at end */ +static int +read_subst(struct demangle_data *d) +{ + size_t idx; + char *str; + + if (d == NULL) + return (-1); + + idx = strtol(d->p + 1, &str, 10); + if (idx == 0 && (errno == EINVAL || errno == ERANGE)) + return (-1); + + assert(idx > 0); + assert(str != NULL); + + d->p = str; + + if (vector_str_push(&d->vec, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (vector_str_push(&d->arg, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (*d->p == '\0') + return (1); + + return (0); +} + +static int +read_subst_iter(struct demangle_data *d) +{ + int i; + size_t idx; + char repeat; + char *str; + + if (d == NULL) + return (-1); + + ++d->p; + assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); + + repeat = *d->p - 48; + + assert(repeat > 1); + + ++d->p; + + idx = strtol(d->p, &str, 10); + if (idx == 0 && (errno == EINVAL || errno == ERANGE)) + return (-1); + + assert(idx > 0); + assert(str != NULL); + + d->p = str; + + for (i = 0; i < repeat ; ++i) { + if (vector_str_push(&d->vec, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (vector_str_push(&d->arg, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (i != repeat - 1 && + vector_str_push(&d->vec, ", ", 2) == false) + return (-1); + } + + if (*d->p == '\0') + return (1); + + return (0); +} + +static bool +read_type(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + + while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' || + *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' || + *d->p == 'M') { + switch (*d->p) { + case 'U' : + ++d->p; + + if (vector_str_push(&d->vec, "unsigned ", 9) == false) + return (false); + + break; + case 'C' : + ++d->p; + + if (*d->p == 'P') + d->cnst = true; + else { + if (vector_str_push(&d->vec, "const ", 6) == + false) + return (false); + } + + break; + case 'V' : + ++d->p; + + if (vector_str_push(&d->vec, "volatile ", 9) == false) + return (false); + + break; + case 'S' : + ++d->p; + + if (vector_str_push(&d->vec, "signed ", 7) == false) + return (false); + + break; + case 'P' : + ++d->p; + + if (*d->p == 'F') + return (read_func_ptr(d)); + else + d->ptr = true; + + break; + case 'R' : + ++d->p; + + d->ref = true; + + break; + case 'F' : + break; + case 'A' : + ++d->p; + + if (read_array(d) == false) + return (false); + + break; + case 'M' : + ++d->p; + + if (read_memptr(d) == false) + return (false); + + break; + default : + break; + }; + }; + + if (ELFTC_ISDIGIT(*d->p)) + return (read_class(d)); + + switch (*d->p) { + case 'Q' : + ++d->p; + + return (read_qual_name(d)); + case 'v' : + ++d->p; + + return (vector_str_push(&d->vec, "void", 4)); + case 'c' : + ++d->p; + + return (vector_str_push(&d->vec, "char", 4)); + case 's' : + ++d->p; + + return (vector_str_push(&d->vec, "short", 5)); + case 'i' : + ++d->p; + + return (vector_str_push(&d->vec, "int", 3)); + case 'l' : + ++d->p; + + return (vector_str_push(&d->vec, "long", 4)); + case 'f' : + ++d->p; + + return (vector_str_push(&d->vec, "float", 5)); + case 'd': + ++d->p; + + return (vector_str_push(&d->vec, "double", 6)); + case 'r': + ++d->p; + + return (vector_str_push(&d->vec, "long double", 11)); + case 'e': + ++d->p; + + return (vector_str_push(&d->vec, "...", 3)); + default: + return (false); + }; + + /* NOTREACHED */ + return (false); +} diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c b/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c new file mode 100644 index 000000000000..4fe141b3b33c --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c @@ -0,0 +1,1376 @@ +/*- + * Copyright (c) 2008 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_dem_gnu2.c 2065 2011-10-26 15:24:47Z jkoshy $"); + +/** + * @file cpp_demangle_gnu2.c + * @brief Decode function name encoding in GNU 2. + * + * Function name encoding in GNU 2 based on ARM style. + */ + +enum encode_type { + ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER, + ENCODE_OP_TF, ENCODE_OP_TI, ENCODE_OP_VT +}; + +struct cstring { + char *buf; + size_t size; +}; + +struct demangle_data { + bool ptr, ref, cnst, array, cnst_fn, class_name; + struct cstring array_str; + const char *p; + enum encode_type type; + struct vector_str vec; + struct vector_str arg; +}; + +#define SIMPLE_HASH(x,y) (64 * x + y) +#define CPP_DEMANGLE_GNU2_TRY 128 + +static void dest_cstring(struct cstring *); +static void dest_demangle_data(struct demangle_data *); +static bool init_cstring(struct cstring *, size_t); +static bool init_demangle_data(struct demangle_data *); +static bool push_CTDT(const char *, size_t, struct vector_str *); +static bool read_array(struct demangle_data *); +static bool read_class(struct demangle_data *); +static bool read_func(struct demangle_data *); +static bool read_func_name(struct demangle_data *); +static bool read_func_ptr(struct demangle_data *); +static bool read_memptr(struct demangle_data *); +static bool read_op(struct demangle_data *); +static bool read_op_user(struct demangle_data *); +static bool read_qual_name(struct demangle_data *); +static int read_subst(struct demangle_data *); +static int read_subst_iter(struct demangle_data *); +static bool read_type(struct demangle_data *); + +/** + * @brief Decode the input string by the GNU 2 style. + * + * @return New allocated demangled string or NULL if failed. + */ +char * +cpp_demangle_gnu2(const char *org) +{ + struct demangle_data d; + size_t arg_begin, arg_len; + unsigned int try; + char *rtn, *arg; + + if (org == NULL) + return (NULL); + + if (init_demangle_data(&d) == false) + return (NULL); + + try = 0; + rtn = NULL; + + d.p = org; + if (read_func_name(&d) == false) + goto clean; + + switch (d.type) { + case ENCODE_FUNC : + case ENCODE_OP : + break; + + case ENCODE_OP_CT : + if (push_CTDT("::", 2, &d.vec) == false) + goto clean; + + break; + case ENCODE_OP_DT : + if (push_CTDT("::~", 3, &d.vec) == false) + goto clean; + + if (vector_str_push(&d.vec, "(void)", 6) == false) + goto clean; + + goto flat; + case ENCODE_OP_USER : + case ENCODE_OP_TF : + case ENCODE_OP_TI : + case ENCODE_OP_VT : + goto flat; + }; + + if (*d.p == 'F') + ++d.p; + else if (*d.p == '\0') { + if (d.class_name == true) { + if (vector_str_push(&d.vec, "(void)", 6) == false) + goto clean; + + goto flat; + } else + goto clean; + } + + /* start argument types */ + if (vector_str_push(&d.vec, "(", 1) == false) + goto clean; + + for (;;) { + if (*d.p == 'T') { + const int rtn_subst = read_subst(&d); + + if (rtn_subst == -1) + goto clean; + else if (rtn_subst == 1) + break; + + continue; + } + + if (*d.p == 'N') { + const int rtn_subst_iter = read_subst_iter(&d); + + if (rtn_subst_iter == -1) + goto clean; + else if(rtn_subst_iter == 1) + break; + + continue; + } + + arg_begin = d.vec.size; + + if (read_type(&d) == false) + goto clean; + + if (d.ptr == true) { + if (vector_str_push(&d.vec, "*", 1) == false) + goto clean; + + d.ptr = false; + } + + if (d.ref == true) { + if (vector_str_push(&d.vec, "&", 1) == false) + goto clean; + + d.ref = false; + } + + if (d.cnst == true) { + if (vector_str_push(&d.vec, " const", 6) == false) + goto clean; + + d.cnst = false; + } + + if (d.array == true) { + if (vector_str_push(&d.vec, d.array_str.buf, + d.array_str.size) == false) + goto clean; + + dest_cstring(&d.array_str); + d.array = false; + } + + if (*d.p == '\0') + break; + + if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1, + &arg_len)) == NULL) + goto clean; + + if (vector_str_push(&d.arg, arg, arg_len) == false) + goto clean; + + free(arg); + + if (vector_str_push(&d.vec, ", ", 2) == false) + goto clean; + + if (++try > CPP_DEMANGLE_GNU2_TRY) + goto clean; + } + + /* end argument types */ + if (vector_str_push(&d.vec, ")", 1) == false) + goto clean; +flat: + if (d.cnst_fn == true && vector_str_push(&d.vec, " const", 6) == false) + goto clean; + + rtn = vector_str_get_flat(&d.vec, NULL); +clean: + dest_demangle_data(&d); + + return (rtn); +} + +/** + * @brief Test input string is encoded by the GNU 2 style. + * + * @return True if input string is encoded by the GNU 2 style. + */ +bool +is_cpp_mangled_gnu2(const char *org) +{ + char *str; + bool rtn = false; + + if (org == NULL) + return (false); + + /* search valid text to end */ + str = strstr(org, "__"); + while (str != NULL) { + if (*(str + 2) != '\0') { + if (*(str + 2) == 'C' || + *(str + 2) == 'F' || + *(str + 2) == 'Q' || + ELFTC_ISDIGIT(*(str + 2))) { + rtn |= true; + + break; + } + + if (*(str + 3) != '\0') { + switch (SIMPLE_HASH(*(str + 2), *(str + 3))) { + case SIMPLE_HASH('m', 'l') : + case SIMPLE_HASH('d', 'v') : + case SIMPLE_HASH('m', 'd') : + case SIMPLE_HASH('p', 'l') : + case SIMPLE_HASH('m', 'i') : + case SIMPLE_HASH('l', 's') : + case SIMPLE_HASH('r', 's') : + case SIMPLE_HASH('e', 'q') : + case SIMPLE_HASH('n', 'e') : + case SIMPLE_HASH('l', 't') : + case SIMPLE_HASH('g', 't') : + case SIMPLE_HASH('l', 'e') : + case SIMPLE_HASH('g', 'e') : + case SIMPLE_HASH('a', 'd') : + case SIMPLE_HASH('o', 'r') : + case SIMPLE_HASH('e', 'r') : + case SIMPLE_HASH('a', 'a') : + case SIMPLE_HASH('o', 'o') : + case SIMPLE_HASH('n', 't') : + case SIMPLE_HASH('c', 'o') : + case SIMPLE_HASH('p', 'p') : + case SIMPLE_HASH('m', 'm') : + case SIMPLE_HASH('a', 's') : + case SIMPLE_HASH('r', 'f') : + case SIMPLE_HASH('a', 'p') : + case SIMPLE_HASH('a', 'm') : + case SIMPLE_HASH('a', 'l') : + case SIMPLE_HASH('a', 'r') : + case SIMPLE_HASH('a', 'o') : + case SIMPLE_HASH('a', 'e') : + case SIMPLE_HASH('c', 'm') : + case SIMPLE_HASH('r', 'm') : + case SIMPLE_HASH('c', 'l') : + case SIMPLE_HASH('v', 'c') : + case SIMPLE_HASH('n', 'w') : + case SIMPLE_HASH('d', 'l') : + case SIMPLE_HASH('o', 'p') : + case SIMPLE_HASH('t', 'f') : + case SIMPLE_HASH('t', 'i') : + rtn |= true; + + break; + }; + } + } + + str = strstr(str + 2, "__"); + } + + rtn |= strstr(org, "_$_") != NULL; + rtn |= strstr(org, "_vt$") != NULL; + + return (rtn); +} + +static void +dest_cstring(struct cstring *s) +{ + + if (s == NULL) + return; + + free(s->buf); + s->buf = NULL; + s->size = 0; +} + +static void +dest_demangle_data(struct demangle_data *d) +{ + + if (d != NULL) { + vector_str_dest(&d->arg); + vector_str_dest(&d->vec); + + dest_cstring(&d->array_str); + } +} + +static bool +init_cstring(struct cstring *s, size_t len) +{ + + if (s == NULL || len <= 1) + return (false); + + if ((s->buf = malloc(sizeof(char) * len)) == NULL) + return (false); + + s->size = len - 1; + + return (true); +} + +static bool +init_demangle_data(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + d->ptr = false; + d->ref = false; + d->cnst = false; + d->array = false; + d->cnst_fn = false; + d->class_name = false; + + d->array_str.buf = NULL; + d->array_str.size = 0; + + d->type = ENCODE_FUNC; + + if (vector_str_init(&d->vec) == false) + return (false); + + if (vector_str_init(&d->arg) == false) { + vector_str_dest(&d->vec); + + return (false); + } + + return (true); +} + +static bool +push_CTDT(const char *s, size_t l, struct vector_str *v) +{ + + if (s == NULL || l == 0 || v == NULL) + return (false); + + if (vector_str_push(v, s, l) == false) + return (false); + + assert(v->size > 1); + + return (vector_str_push(v, v->container[v->size - 2], + strlen(v->container[v->size - 2]))); +} + +static bool +read_array(struct demangle_data *d) +{ + size_t len; + const char *end; + + if (d == NULL || d->p == NULL) + return (false); + + end = d->p; + assert(end != NULL); + + for (;;) { + if (*end == '\0') + return (false); + + if (ELFTC_ISDIGIT(*end) == 0) + break; + + ++end; + } + + if (*end != '_') + return (false); + + len = end - d->p; + assert(len > 0); + + dest_cstring(&d->array_str); + if (init_cstring(&d->array_str, len + 3) == false) + return (false); + + strncpy(d->array_str.buf + 1, d->p, len); + *d->array_str.buf = '['; + *(d->array_str.buf + len + 1) = ']'; + + d->array = true; + d->p = end + 1; + + return (true); +} + +static bool +read_class(struct demangle_data *d) +{ + size_t len; + char *str; + + if (d == NULL) + return (false); + + len = strtol(d->p, &str, 10); + if (len == 0 && (errno == EINVAL || errno == ERANGE)) + return (false); + + assert(len > 0); + assert(str != NULL); + + if (vector_str_push(&d->vec, str, len) == false) + return (false); + + d->p = str + len; + + d->class_name = true; + + return (true); +} + +static bool +read_func(struct demangle_data *d) +{ + size_t len; + const char *name; + char *delim; + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + if ((delim = strstr(d->p, "__")) == NULL) + return (false); + + len = delim - d->p; + assert(len != 0); + + name = d->p; + + d->p = delim + 2; + + if (*d->p == 'C') { + ++d->p; + + d->cnst_fn = true; + } + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + if (read_qual_name(d) == false) + return (false); + } else if (ELFTC_ISDIGIT(*d->p)) { + if (read_class(d) == false) + return (false); + + if (vector_str_push(&d->vec, "::", 2) == false) + return (false); + } + + return (vector_str_push(&d->vec, name, len)); +} + +static bool +read_func_name(struct demangle_data *d) +{ + size_t len; + bool rtn; + char *op_name; + + if (d == NULL) + return (false); + + rtn = false; + op_name = NULL; + + assert(d->p != NULL && "d->p (org str) is NULL"); + + if (*d->p == '_' && *(d->p + 1) == '_') { + d->p += 2; + + /* CTOR */ + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + d->type = ENCODE_OP_CT; + + if (read_qual_name(d) == false) + return (false); + + return (vector_str_pop(&d->vec)); + } else if (ELFTC_ISDIGIT(*d->p)) { + d->type = ENCODE_OP_CT; + + return (read_class(d)); + } + + d->type = ENCODE_OP; + if (read_op(d) == false) { + /* not good condition, start function name with '__' */ + d->type = ENCODE_FUNC; + + if (vector_str_push(&d->vec, "__", 2) == false) + return (false); + + return (read_func(d)); + } + + if (d->type == ENCODE_OP_USER || + d->type == ENCODE_OP_TF || + d->type == ENCODE_OP_TI) + return (true); + + /* skip "__" */ + d->p += 2; + + if (*d->p == 'C') { + ++d->p; + + d->cnst_fn = true; + } + + /* assume delimiter is removed */ + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + assert(d->vec.size > 0); + + len = strlen(d->vec.container[d->vec.size - 1]); + if ((op_name = malloc(sizeof(char) * (len + 1))) + == NULL) + return (false); + + snprintf(op_name, len + 1, "%s", + d->vec.container[d->vec.size - 1]); + vector_str_pop(&d->vec); + + if (read_qual_name(d) == false) + goto clean; + + if (vector_str_push(&d->vec, "::", 2) == false) + goto clean; + + if (vector_str_push(&d->vec, op_name, len) == false) + goto clean; + + rtn = true; + } else if (ELFTC_ISDIGIT(*d->p)) { + assert(d->vec.size > 0); + + len = strlen(d->vec.container[d->vec.size - 1]); + if ((op_name = malloc(sizeof(char) * (len + 1))) + == NULL) + return (false); + + snprintf(op_name, len + 1, "%s", + d->vec.container[d->vec.size - 1]); + vector_str_pop(&d->vec); + + if (read_class(d) == false) + goto clean; + + if (vector_str_push(&d->vec, "::", 2) == false) + goto clean; + + if (vector_str_push(&d->vec, op_name, len) == false) + goto clean; + + rtn = true; + } + } else if (memcmp(d->p, "_$_", 3) == 0) { + /* DTOR */ + d->p += 3; + d->type = ENCODE_OP_DT; + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + if (read_qual_name(d) == false) + return (false); + + return (vector_str_pop(&d->vec)); + } else if (ELFTC_ISDIGIT(*d->p)) + return (read_class(d)); + + return (false); + } else if (memcmp(d->p, "_vt$", 4) == 0) { + /* vtable */ + d->p += 4; + d->type = ENCODE_OP_VT; + + if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) { + ++d->p; + + if (read_qual_name(d) == false) + return (false); + + if (vector_str_pop(&d->vec) == false) + return (false); + } else if (ELFTC_ISDIGIT(*d->p)) { + if (read_class(d) == false) + return (false); + } + + return (vector_str_push(&d->vec, " virtual table", 14)); + } else + return (read_func(d)); +clean: + free(op_name); + + return (rtn); +} + +/* Read function ptr type */ +static bool +read_func_ptr(struct demangle_data *d) +{ + struct demangle_data fptr; + size_t arg_len, rtn_len; + char *arg_type, *rtn_type; + int lim; + + if (d == NULL) + return (false); + + if (init_demangle_data(&fptr) == false) + return (false); + + fptr.p = d->p + 1; + lim = 0; + arg_type = NULL; + rtn_type = NULL; + + for (;;) { + if (read_type(&fptr) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + if (fptr.ptr == true) { + if (vector_str_push(&fptr.vec, "*", 1) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.ptr = false; + } + + if (fptr.ref == true) { + if (vector_str_push(&fptr.vec, "&", 1) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.ref = false; + } + + if (fptr.cnst == true) { + if (vector_str_push(&fptr.vec, " const", 6) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + fptr.cnst = false; + } + + if (*fptr.p == '_') + break; + + if (vector_str_push(&fptr.vec, ", ", 2) == false) { + dest_demangle_data(&fptr); + + return (false); + } + + if (++lim > CPP_DEMANGLE_GNU2_TRY) { + + dest_demangle_data(&fptr); + + return (false); + } + } + + arg_type = vector_str_get_flat(&fptr.vec, &arg_len); + /* skip '_' */ + d->p = fptr.p + 1; + + dest_demangle_data(&fptr); + + if (init_demangle_data(&fptr) == false) { + free(arg_type); + + return (false); + } + + fptr.p = d->p; + lim = 0; + + if (read_type(&fptr) == false) { + free(arg_type); + dest_demangle_data(&fptr); + + return (false); + } + + rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len); + d->p = fptr.p; + + + dest_demangle_data(&fptr); + + if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) { + free(rtn_type); + free(arg_type); + + return (false); + } + + free(rtn_type); + + if (vector_str_push(&d->vec, " (*)(", 5) == false) { + free(arg_type); + + return (false); + } + + if (vector_str_push(&d->vec, arg_type, arg_len) == false) { + free(arg_type); + + return (false); + } + + free(arg_type); + + return (vector_str_push(&d->vec, ")", 1)); +} + +static bool +read_memptr(struct demangle_data *d) +{ + struct demangle_data mptr; + size_t len; + bool rtn; + char *mptr_str; + + if (d == NULL || d->p == NULL) + return (false); + + if (init_demangle_data(&mptr) == false) + return (false); + + rtn = false; + mptr_str = NULL; + + mptr.p = d->p; + if (*mptr.p == 'Q') { + ++mptr.p; + + if (read_qual_name(&mptr) == false) + goto clean; + } else if (read_class(&mptr) == false) + goto clean; + + d->p = mptr.p; + + if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL) + goto clean; + + if (vector_str_push(&d->vec, mptr_str, len) == false) + goto clean; + + if (vector_str_push(&d->vec, "::*", 3) == false) + goto clean; + + rtn = true; +clean: + free(mptr_str); + dest_demangle_data(&mptr); + + return (rtn); +} + +static bool +read_op(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + + switch (SIMPLE_HASH(*(d->p), *(d->p+1))) { + case SIMPLE_HASH('m', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator*", 9)); + case SIMPLE_HASH('d', 'v') : + d->p += 2; + return (vector_str_push(&d->vec, "operator/", 9)); + case SIMPLE_HASH('m', 'd') : + d->p += 2; + return (vector_str_push(&d->vec, "operator%", 9)); + case SIMPLE_HASH('p', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator+", 9)); + case SIMPLE_HASH('m', 'i') : + d->p += 2; + return (vector_str_push(&d->vec, "operator-", 9)); + case SIMPLE_HASH('l', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<<", 10)); + case SIMPLE_HASH('r', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>>", 10)); + case SIMPLE_HASH('e', 'q') : + d->p += 2; + return (vector_str_push(&d->vec, "operator==", 10)); + case SIMPLE_HASH('n', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator!=", 10)); + case SIMPLE_HASH('l', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<", 9)); + case SIMPLE_HASH('g', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>", 9)); + case SIMPLE_HASH('l', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator<=", 10)); + case SIMPLE_HASH('g', 'e') : + d->p += 2; + return (vector_str_push(&d->vec, "operator>=", 10)); + case SIMPLE_HASH('a', 'd') : + d->p += 2; + if (*d->p == 'v') { + ++d->p; + return (vector_str_push(&d->vec, "operator/=", + 10)); + } else + return (vector_str_push(&d->vec, "operator&", 9)); + case SIMPLE_HASH('o', 'r') : + d->p += 2; + return (vector_str_push(&d->vec, "operator|", 9)); + case SIMPLE_HASH('e', 'r') : + d->p += 2; + return (vector_str_push(&d->vec, "operator^", 9)); + case SIMPLE_HASH('a', 'a') : + d->p += 2; + if (*d->p == 'd') { + ++d->p; + return (vector_str_push(&d->vec, "operator&=", + 10)); + } else + return (vector_str_push(&d->vec, "operator&&", + 10)); + case SIMPLE_HASH('o', 'o') : + d->p += 2; + return (vector_str_push(&d->vec, "operator||", 10)); + case SIMPLE_HASH('n', 't') : + d->p += 2; + return (vector_str_push(&d->vec, "operator!", 9)); + case SIMPLE_HASH('c', 'o') : + d->p += 2; + return (vector_str_push(&d->vec, "operator~", 9)); + case SIMPLE_HASH('p', 'p') : + d->p += 2; + return (vector_str_push(&d->vec, "operator++", 10)); + case SIMPLE_HASH('m', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator--", 10)); + case SIMPLE_HASH('a', 's') : + d->p += 2; + return (vector_str_push(&d->vec, "operator=", 9)); + case SIMPLE_HASH('r', 'f') : + d->p += 2; + return (vector_str_push(&d->vec, "operator->", 10)); + case SIMPLE_HASH('a', 'p') : + /* apl */ + if (*(d->p + 2) != 'l') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator+=", 10)); + case SIMPLE_HASH('a', 'm') : + d->p += 2; + if (*d->p == 'i') { + ++d->p; + return (vector_str_push(&d->vec, "operator-=", + 10)); + } else if (*d->p == 'u') { + ++d->p; + return (vector_str_push(&d->vec, "operator*=", + 10)); + } else if (*d->p == 'd') { + ++d->p; + return (vector_str_push(&d->vec, "operator%=", + 10)); + } + + return (false); + case SIMPLE_HASH('a', 'l') : + /* als */ + if (*(d->p + 2) != 's') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator<<=", 11)); + case SIMPLE_HASH('a', 'r') : + /* ars */ + if (*(d->p + 2) != 's') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator>>=", 11)); + case SIMPLE_HASH('a', 'o') : + /* aor */ + if (*(d->p + 2) != 'r') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator|=", 10)); + case SIMPLE_HASH('a', 'e') : + /* aer */ + if (*(d->p + 2) != 'r') + return (false); + + d->p += 3; + return (vector_str_push(&d->vec, "operator^=", 10)); + case SIMPLE_HASH('c', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator,", 9)); + case SIMPLE_HASH('r', 'm') : + d->p += 2; + return (vector_str_push(&d->vec, "operator->*", 11)); + case SIMPLE_HASH('c', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "()", 2)); + case SIMPLE_HASH('v', 'c') : + d->p += 2; + return (vector_str_push(&d->vec, "[]", 2)); + case SIMPLE_HASH('n', 'w') : + d->p += 2; + return (vector_str_push(&d->vec, "operator new()", 14)); + case SIMPLE_HASH('d', 'l') : + d->p += 2; + return (vector_str_push(&d->vec, "operator delete()", + 17)); + case SIMPLE_HASH('o', 'p') : + /* __op__ */ + d->p += 2; + + d->type = ENCODE_OP_USER; + + return (read_op_user(d)); + case SIMPLE_HASH('t', 'f') : + d->p += 2; + d->type = ENCODE_OP_TF; + + if (read_type(d) == false) + return (false); + + return (vector_str_push(&d->vec, " type_info function", 19)); + case SIMPLE_HASH('t', 'i') : + d->p += 2; + d->type = ENCODE_OP_TI; + + if (read_type(d) == false) + return (false); + + return (vector_str_push(&d->vec, " type_info node", 15)); + default : + return (false); + }; +} + +static bool +read_op_user(struct demangle_data *d) +{ + struct demangle_data from, to; + size_t from_len, to_len; + bool rtn; + char *from_str, *to_str; + + if (d == NULL) + return (false); + + if (init_demangle_data(&from) == false) + return (false); + + rtn = false; + from_str = NULL; + to_str = NULL; + if (init_demangle_data(&to) == false) + goto clean; + + to.p = d->p; + if (*to.p == 'Q') { + ++to.p; + + if (read_qual_name(&to) == false) + goto clean; + + /* pop last '::' */ + if (vector_str_pop(&to.vec) == false) + goto clean; + } else { + if (read_class(&to) == false) + goto clean; + + /* skip '__' */ + to.p += 2; + } + + if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL) + goto clean; + + from.p = to.p; + if (*from.p == 'Q') { + ++from.p; + + if (read_qual_name(&from) == false) + goto clean; + + /* pop last '::' */ + if (vector_str_pop(&from.vec) == false) + goto clean; + } else if (read_class(&from) == false) + goto clean; + + if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL) + goto clean; + + if (vector_str_push(&d->vec, from_str, from_len) == false) + goto clean; + + if (vector_str_push(&d->vec, "::operator ", 11) == false) + goto clean; + + if (vector_str_push(&d->vec, to_str, to_len) == false) + goto clean; + + rtn = vector_str_push(&d->vec, "()", 2); +clean: + free(to_str); + free(from_str); + dest_demangle_data(&to); + dest_demangle_data(&from); + + return (rtn); +} + +/* single digit + class names */ +static bool +read_qual_name(struct demangle_data *d) +{ + int i; + char num; + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); + + num = *d->p - 48; + + assert(num > 0); + + ++d->p; + for (i = 0; i < num ; ++i) { + if (read_class(d) == false) + return (false); + + if (vector_str_push(&d->vec, "::", 2) == false) + return (false); + } + + if (*d->p != '\0') + d->p = d->p + 2; + + return (true); +} + +/* Return -1 at fail, 0 at success, and 1 at end */ +static int +read_subst(struct demangle_data *d) +{ + size_t idx; + char *str; + + if (d == NULL) + return (-1); + + idx = strtol(d->p + 1, &str, 10); + if (idx == 0 && (errno == EINVAL || errno == ERANGE)) + return (-1); + + assert(idx > 0); + assert(str != NULL); + + d->p = str; + + if (vector_str_push(&d->vec, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (vector_str_push(&d->arg, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (*d->p == '\0') + return (1); + + return (0); +} + +static int +read_subst_iter(struct demangle_data *d) +{ + int i; + size_t idx; + char repeat; + char *str; + + if (d == NULL) + return (-1); + + ++d->p; + assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range"); + + repeat = *d->p - 48; + + assert(repeat > 1); + + ++d->p; + + idx = strtol(d->p, &str, 10); + if (idx == 0 && (errno == EINVAL || errno == ERANGE)) + return (-1); + + assert(idx > 0); + assert(str != NULL); + + d->p = str; + + for (i = 0; i < repeat ; ++i) { + if (vector_str_push(&d->vec, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (vector_str_push(&d->arg, d->arg.container[idx - 1], + strlen(d->arg.container[idx - 1])) == false) + return (-1); + + if (i != repeat - 1 && + vector_str_push(&d->vec, ", ", 2) == false) + return (-1); + } + + if (*d->p == '\0') + return (1); + + return (0); +} + +static bool +read_type(struct demangle_data *d) +{ + + if (d == NULL) + return (false); + + assert(d->p != NULL && "d->p (org str) is NULL"); + + while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' || + *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' || + *d->p == 'M') { + switch (*d->p) { + case 'U' : + ++d->p; + + if (vector_str_push(&d->vec, "unsigned ", 9) == false) + return (false); + + break; + case 'C' : + ++d->p; + + if (*d->p == 'P') + d->cnst = true; + else { + if (vector_str_push(&d->vec, "const ", 6) == + false) + return (false); + } + + break; + case 'V' : + ++d->p; + + if (vector_str_push(&d->vec, "volatile ", 9) == false) + return (false); + + break; + case 'S' : + ++d->p; + + if (vector_str_push(&d->vec, "signed ", 7) == false) + return (false); + + break; + case 'P' : + ++d->p; + + if (*d->p == 'F') + return (read_func_ptr(d)); + else + d->ptr = true; + + break; + case 'R' : + ++d->p; + + d->ref = true; + + break; + case 'F' : + break; + case 'A' : + ++d->p; + + if (read_array(d) == false) + return (false); + + break; + case 'M' : + ++d->p; + + if (read_memptr(d) == false) + return (false); + + break; + default : + break; + }; + }; + + if (ELFTC_ISDIGIT(*d->p)) + return (read_class(d)); + + switch (*d->p) { + case 'Q' : + ++d->p; + + return (read_qual_name(d)); + case 'v' : + ++d->p; + + return (vector_str_push(&d->vec, "void", 4)); + case 'b': + ++d->p; + + return(vector_str_push(&d->vec, "bool", 4)); + case 'c' : + ++d->p; + + return (vector_str_push(&d->vec, "char", 4)); + case 's' : + ++d->p; + + return (vector_str_push(&d->vec, "short", 5)); + case 'i' : + ++d->p; + + return (vector_str_push(&d->vec, "int", 3)); + case 'l' : + ++d->p; + + return (vector_str_push(&d->vec, "long", 4)); + case 'f' : + ++d->p; + + return (vector_str_push(&d->vec, "float", 5)); + case 'd': + ++d->p; + + return (vector_str_push(&d->vec, "double", 6)); + case 'r': + ++d->p; + + return (vector_str_push(&d->vec, "long double", 11)); + case 'e': + ++d->p; + + return (vector_str_push(&d->vec, "...", 3)); + case 'w': + ++d->p; + + return (vector_str_push(&d->vec, "wchar_t", 7)); + case 'x': + ++d->p; + + return (vector_str_push(&d->vec, "long long", 9)); + default: + return (false); + }; + + /* NOTREACHED */ + return (false); +} diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c new file mode 100644 index 000000000000..bd54f549ddb8 --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c @@ -0,0 +1,3238 @@ +/*- + * Copyright (c) 2007 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 2179 2011-11-18 03:05:47Z jkoshy $"); + +/** + * @file cpp_demangle.c + * @brief Decode IA-64 C++ ABI style implementation. + * + * IA-64 standard ABI(Itanium C++ ABI) references. + * + * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n + * http://www.codesourcery.com/cxx-abi/abi-mangling.html + */ + +enum type_qualifier { + TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT, + TYPE_CST +}; + +struct vector_type_qualifier { + size_t size, capacity; + enum type_qualifier *q_container; + struct vector_str ext_name; +}; + +enum read_cmd { + READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL, + READ_TYPE, READ_FUNC, READ_PTRMEM +}; + +struct vector_read_cmd { + size_t size, capacity; + enum read_cmd *r_container; +}; + +struct cpp_demangle_data { + struct vector_str output; /* output string vector */ + struct vector_str output_tmp; + struct vector_str subst; /* substitution string vector */ + struct vector_str tmpl; + struct vector_str class_type; + struct vector_read_cmd cmd; + bool paren; /* parenthesis opened */ + bool pfirst; /* first element of parameter */ + bool mem_rst; /* restrict member function */ + bool mem_vat; /* volatile member function */ + bool mem_cst; /* const member function */ + int func_type; + const char *cur; /* current mangled name ptr */ + const char *last_sname; /* last source name */ +}; + +#define CPP_DEMANGLE_TRY_LIMIT 128 +#define FLOAT_SPRINTF_TRY_LIMIT 5 +#define FLOAT_QUADRUPLE_BYTES 16 +#define FLOAT_EXTENED_BYTES 10 + +#define SIMPLE_HASH(x,y) (64 * x + y) + +static void cpp_demangle_data_dest(struct cpp_demangle_data *); +static int cpp_demangle_data_init(struct cpp_demangle_data *, + const char *); +static int cpp_demangle_get_subst(struct cpp_demangle_data *, size_t); +static int cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t); +static int cpp_demangle_push_fp(struct cpp_demangle_data *, + char *(*)(const char *, size_t)); +static int cpp_demangle_push_str(struct cpp_demangle_data *, const char *, + size_t); +static int cpp_demangle_push_subst(struct cpp_demangle_data *, + const char *, size_t); +static int cpp_demangle_push_subst_v(struct cpp_demangle_data *, + struct vector_str *); +static int cpp_demangle_push_type_qualifier(struct cpp_demangle_data *, + struct vector_type_qualifier *, const char *); +static int cpp_demangle_read_array(struct cpp_demangle_data *); +static int cpp_demangle_read_encoding(struct cpp_demangle_data *); +static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *); +static int cpp_demangle_read_expression(struct cpp_demangle_data *); +static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *, + const char *, size_t); +static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *, + const char *, size_t); +static int cpp_demangle_read_expression_trinary(struct cpp_demangle_data *, + const char *, size_t, const char *, size_t); +static int cpp_demangle_read_function(struct cpp_demangle_data *, int *, + struct vector_type_qualifier *); +static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata); +static int cpp_demangle_read_local_name(struct cpp_demangle_data *); +static int cpp_demangle_read_name(struct cpp_demangle_data *); +static int cpp_demangle_read_nested_name(struct cpp_demangle_data *); +static int cpp_demangle_read_number(struct cpp_demangle_data *, long *); +static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *); +static int cpp_demangle_read_offset(struct cpp_demangle_data *); +static int cpp_demangle_read_offset_number(struct cpp_demangle_data *); +static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *); +static int cpp_demangle_read_sname(struct cpp_demangle_data *); +static int cpp_demangle_read_subst(struct cpp_demangle_data *); +static int cpp_demangle_read_subst_std(struct cpp_demangle_data *); +static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *, + const char *, size_t); +static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *); +static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *); +static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *); +static int cpp_demangle_read_type(struct cpp_demangle_data *, int); +static int cpp_demangle_read_uqname(struct cpp_demangle_data *); +static int cpp_demangle_read_v_offset(struct cpp_demangle_data *); +static char *decode_fp_to_double(const char *, size_t); +static char *decode_fp_to_float(const char *, size_t); +static char *decode_fp_to_float128(const char *, size_t); +static char *decode_fp_to_float80(const char *, size_t); +static char *decode_fp_to_long_double(const char *, size_t); +static int hex_to_dec(char); +static void vector_read_cmd_dest(struct vector_read_cmd *); +static int vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd); +static int vector_read_cmd_init(struct vector_read_cmd *); +static int vector_read_cmd_pop(struct vector_read_cmd *); +static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd); +static void vector_type_qualifier_dest(struct vector_type_qualifier *); +static int vector_type_qualifier_init(struct vector_type_qualifier *); +static int vector_type_qualifier_push(struct vector_type_qualifier *, + enum type_qualifier); + +int cpp_demangle_gnu3_push_head; + +/** + * @brief Decode the input string by IA-64 C++ ABI style. + * + * GNU GCC v3 use IA-64 standard ABI. + * @return New allocated demangled string or NULL if failed. + * @todo 1. Testing and more test case. 2. Code cleaning. + */ +char * +cpp_demangle_gnu3(const char *org) +{ + struct cpp_demangle_data ddata; + ssize_t org_len; + unsigned int limit; + char *rtn; + + if (org == NULL || (org_len = strlen(org)) < 2) + return (NULL); + + if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) { + if ((rtn = malloc(org_len + 19)) == NULL) + return (NULL); + snprintf(rtn, org_len + 19, + "global constructors keyed to %s", org + 11); + return (rtn); + } + + if (org[0] != '_' || org[1] != 'Z') + return (NULL); + + if (!cpp_demangle_data_init(&ddata, org + 2)) + return (NULL); + + cpp_demangle_gnu3_push_head = 0; + rtn = NULL; + + if (!cpp_demangle_read_encoding(&ddata)) + goto clean; + + limit = 0; + while (*ddata.cur != '\0') { + /* + * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4 + */ + if (*ddata.cur == '@' && *(ddata.cur + 1) == '@') + break; + if (!cpp_demangle_read_type(&ddata, 1)) + goto clean; + if (limit++ > CPP_DEMANGLE_TRY_LIMIT) + goto clean; + } + + if (ddata.output.size == 0) + goto clean; + if (ddata.paren && !vector_str_push(&ddata.output, ")", 1)) + goto clean; + if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9)) + goto clean; + if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6)) + goto clean; + if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9)) + goto clean; + + rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL); + +clean: + cpp_demangle_data_dest(&ddata); + + return (rtn); +} + +static void +cpp_demangle_data_dest(struct cpp_demangle_data *d) +{ + + if (d == NULL) + return; + + vector_read_cmd_dest(&d->cmd); + vector_str_dest(&d->class_type); + vector_str_dest(&d->tmpl); + vector_str_dest(&d->subst); + vector_str_dest(&d->output_tmp); + vector_str_dest(&d->output); +} + +static int +cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur) +{ + + if (d == NULL || cur == NULL) + return (0); + + if (!vector_str_init(&d->output)) + return (0); + if (!vector_str_init(&d->output_tmp)) + goto clean1; + if (!vector_str_init(&d->subst)) + goto clean2; + if (!vector_str_init(&d->tmpl)) + goto clean3; + if (!vector_str_init(&d->class_type)) + goto clean4; + if (!vector_read_cmd_init(&d->cmd)) + goto clean5; + + assert(d->output.container != NULL); + assert(d->output_tmp.container != NULL); + assert(d->subst.container != NULL); + assert(d->tmpl.container != NULL); + assert(d->class_type.container != NULL); + + d->paren = false; + d->pfirst = false; + d->mem_rst = false; + d->mem_vat = false; + d->mem_cst = false; + d->func_type = 0; + d->cur = cur; + d->last_sname = NULL; + + return (1); + +clean5: + vector_str_dest(&d->class_type); +clean4: + vector_str_dest(&d->tmpl); +clean3: + vector_str_dest(&d->subst); +clean2: + vector_str_dest(&d->output_tmp); +clean1: + vector_str_dest(&d->output); + + return (0); +} + +static int +cpp_demangle_push_fp(struct cpp_demangle_data *ddata, + char *(*decoder)(const char *, size_t)) +{ + size_t len; + int rtn; + const char *fp; + char *f; + + if (ddata == NULL || decoder == NULL) + return (0); + + fp = ddata->cur; + while (*ddata->cur != 'E') + ++ddata->cur; + ++ddata->cur; + + if ((f = decoder(fp, ddata->cur - fp)) == NULL) + return (0); + + rtn = 0; + if ((len = strlen(f)) > 0) + rtn = cpp_demangle_push_str(ddata, f, len); + + free(f); + + return (rtn); +} + +static int +cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str, + size_t len) +{ + + if (ddata == NULL || str == NULL || len == 0) + return (0); + + if (cpp_demangle_gnu3_push_head > 0) + return (vector_str_push(&ddata->output_tmp, str, len)); + + return (vector_str_push(&ddata->output, str, len)); +} + +static int +cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str, + size_t len) +{ + + if (ddata == NULL || str == NULL || len == 0) + return (0); + + if (!vector_str_find(&ddata->subst, str, len)) + return (vector_str_push(&ddata->subst, str, len)); + + return (1); +} + +static int +cpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v) +{ + size_t str_len; + int rtn; + char *str; + + if (ddata == NULL || v == NULL) + return (0); + + if ((str = vector_str_get_flat(v, &str_len)) == NULL) + return (0); + + rtn = cpp_demangle_push_subst(ddata, str, str_len); + + free(str); + + return (rtn); +} + +static int +cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata, + struct vector_type_qualifier *v, const char *type_str) +{ + struct vector_str subst_v; + size_t idx, e_idx, e_len; + int rtn; + char *buf; + + if (ddata == NULL || v == NULL) + return (0); + + if ((idx = v->size) == 0) + return (1); + + rtn = 0; + if (type_str != NULL) { + if (!vector_str_init(&subst_v)) + return (0); + if (!vector_str_push(&subst_v, type_str, strlen(type_str))) + goto clean; + } + + e_idx = 0; + while (idx > 0) { + switch (v->q_container[idx - 1]) { + case TYPE_PTR: + if (!cpp_demangle_push_str(ddata, "*", 1)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, "*", 1)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_REF: + if (!cpp_demangle_push_str(ddata, "&", 1)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, "&", 1)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_CMX: + if (!cpp_demangle_push_str(ddata, " complex", 8)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, " complex", 8)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_IMG: + if (!cpp_demangle_push_str(ddata, " imaginary", 10)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, " imaginary", 10)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_EXT: + if (e_idx > v->ext_name.size - 1) + goto clean; + if ((e_len = strlen(v->ext_name.container[e_idx])) == 0) + goto clean; + if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL) + goto clean; + + memcpy(buf, " ", 1); + memcpy(buf + 1, v->ext_name.container[e_idx], e_len); + + if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) { + free(buf); + goto clean; + } + + if (type_str != NULL) { + if (!vector_str_push(&subst_v, buf, + e_len + 1)) { + free(buf); + goto clean; + } + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) { + free(buf); + goto clean; + } + } + free(buf); + ++e_idx; + break; + + case TYPE_RST: + if (!cpp_demangle_push_str(ddata, " restrict", 9)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, " restrict", 9)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_VAT: + if (!cpp_demangle_push_str(ddata, " volatile", 9)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, " volatile", 9)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + case TYPE_CST: + if (!cpp_demangle_push_str(ddata, " const", 6)) + goto clean; + if (type_str != NULL) { + if (!vector_str_push(&subst_v, " const", 6)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &subst_v)) + goto clean; + } + break; + + }; + --idx; + } + + rtn = 1; +clean: + if (type_str != NULL) + vector_str_dest(&subst_v); + + return (rtn); +} + +static int +cpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx) +{ + size_t len; + + if (ddata == NULL || ddata->subst.size <= idx) + return (0); + if ((len = strlen(ddata->subst.container[idx])) == 0) + return (0); + if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len)) + return (0); + + /* skip '_' */ + ++ddata->cur; + + return (1); +} + +static int +cpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx) +{ + size_t len; + + if (ddata == NULL || ddata->tmpl.size <= idx) + return (0); + if ((len = strlen(ddata->tmpl.container[idx])) == 0) + return (0); + if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len)) + return (0); + + ++ddata->cur; + + return (1); +} + +static int +cpp_demangle_read_array(struct cpp_demangle_data *ddata) +{ + size_t i, num_len, exp_len, p_idx, idx; + const char *num; + char *exp; + + if (ddata == NULL || *(++ddata->cur) == '\0') + return (0); + + if (*ddata->cur == '_') { + if (*(++ddata->cur) == '\0') + return (0); + + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + + if (!cpp_demangle_push_str(ddata, "[]", 2)) + return (0); + } else { + if (ELFTC_ISDIGIT(*ddata->cur) != 0) { + num = ddata->cur; + while (ELFTC_ISDIGIT(*ddata->cur) != 0) + ++ddata->cur; + if (*ddata->cur != '_') + return (0); + num_len = ddata->cur - num; + assert(num_len > 0); + if (*(++ddata->cur) == '\0') + return (0); + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + if (!cpp_demangle_push_str(ddata, "[", 1)) + return (0); + if (!cpp_demangle_push_str(ddata, num, num_len)) + return (0); + if (!cpp_demangle_push_str(ddata, "]", 1)) + return (0); + } else { + p_idx = ddata->output.size; + if (!cpp_demangle_read_expression(ddata)) + return (0); + if ((exp = vector_str_substr(&ddata->output, p_idx, + ddata->output.size - 1, &exp_len)) == NULL) + return (0); + idx = ddata->output.size; + for (i = p_idx; i < idx; ++i) + if (!vector_str_pop(&ddata->output)) { + free(exp); + return (0); + } + if (*ddata->cur != '_') { + free(exp); + return (0); + } + ++ddata->cur; + if (*ddata->cur == '\0') { + free(exp); + return (0); + } + if (!cpp_demangle_read_type(ddata, 0)) { + free(exp); + return (0); + } + if (!cpp_demangle_push_str(ddata, "[", 1)) { + free(exp); + return (0); + } + if (!cpp_demangle_push_str(ddata, exp, exp_len)) { + free(exp); + return (0); + } + if (!cpp_demangle_push_str(ddata, "]", 1)) { + free(exp); + return (0); + } + free(exp); + } + } + + return (1); +} + +static int +cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata) +{ + const char *num; + + if (ddata == NULL || *(++ddata->cur) == '\0') + return (0); + + if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') { + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_encoding(ddata)) + return (0); + ++ddata->cur; + return (1); + } + + switch (*ddata->cur) { + case 'b': + switch (*(++ddata->cur)) { + case '0': + return (cpp_demangle_push_str(ddata, "false", 5)); + case '1': + return (cpp_demangle_push_str(ddata, "true", 4)); + default: + return (0); + }; + + case 'd': + ++ddata->cur; + return (cpp_demangle_push_fp(ddata, decode_fp_to_double)); + + case 'e': + ++ddata->cur; + if (sizeof(long double) == 10) + return (cpp_demangle_push_fp(ddata, + decode_fp_to_double)); + return (cpp_demangle_push_fp(ddata, decode_fp_to_float80)); + + case 'f': + ++ddata->cur; + return (cpp_demangle_push_fp(ddata, decode_fp_to_float)); + + case 'g': + ++ddata->cur; + if (sizeof(long double) == 16) + return (cpp_demangle_push_fp(ddata, + decode_fp_to_double)); + return (cpp_demangle_push_fp(ddata, decode_fp_to_float128)); + + case 'i': + case 'j': + case 'l': + case 'm': + case 'n': + case 's': + case 't': + case 'x': + case 'y': + if (*(++ddata->cur) == 'n') { + if (!cpp_demangle_push_str(ddata, "-", 1)) + return (0); + ++ddata->cur; + } + num = ddata->cur; + while (*ddata->cur != 'E') { + if (!ELFTC_ISDIGIT(*ddata->cur)) + return (0); + ++ddata->cur; + } + ++ddata->cur; + return (cpp_demangle_push_str(ddata, num, ddata->cur - num)); + + default: + return (0); + }; +} + +static int +cpp_demangle_read_expression(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('s', 't'): + ddata->cur += 2; + return (cpp_demangle_read_type(ddata, 0)); + + case SIMPLE_HASH('s', 'r'): + ddata->cur += 2; + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + if (!cpp_demangle_read_uqname(ddata)) + return (0); + if (*ddata->cur == 'I') + return (cpp_demangle_read_tmpl_args(ddata)); + return (1); + + case SIMPLE_HASH('a', 'a'): + /* operator && */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "&&", 2)); + + case SIMPLE_HASH('a', 'd'): + /* operator & (unary) */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "&", 1)); + + case SIMPLE_HASH('a', 'n'): + /* operator & */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "&", 1)); + + case SIMPLE_HASH('a', 'N'): + /* operator &= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "&=", 2)); + + case SIMPLE_HASH('a', 'S'): + /* operator = */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "=", 1)); + + case SIMPLE_HASH('c', 'l'): + /* operator () */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "()", 2)); + + case SIMPLE_HASH('c', 'm'): + /* operator , */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, ",", 1)); + + case SIMPLE_HASH('c', 'o'): + /* operator ~ */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "~", 1)); + + case SIMPLE_HASH('c', 'v'): + /* operator (cast) */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6)); + + case SIMPLE_HASH('d', 'a'): + /* operator delete [] */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "delete []", 9)); + + case SIMPLE_HASH('d', 'e'): + /* operator * (unary) */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "*", 1)); + + case SIMPLE_HASH('d', 'l'): + /* operator delete */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "delete", 6)); + + case SIMPLE_HASH('d', 'v'): + /* operator / */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "/", 1)); + + case SIMPLE_HASH('d', 'V'): + /* operator /= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "/=", 2)); + + case SIMPLE_HASH('e', 'o'): + /* operator ^ */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "^", 1)); + + case SIMPLE_HASH('e', 'O'): + /* operator ^= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "^=", 2)); + + case SIMPLE_HASH('e', 'q'): + /* operator == */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "==", 2)); + + case SIMPLE_HASH('g', 'e'): + /* operator >= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, ">=", 2)); + + case SIMPLE_HASH('g', 't'): + /* operator > */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, ">", 1)); + + case SIMPLE_HASH('i', 'x'): + /* operator [] */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "[]", 2)); + + case SIMPLE_HASH('l', 'e'): + /* operator <= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "<=", 2)); + + case SIMPLE_HASH('l', 's'): + /* operator << */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "<<", 2)); + + case SIMPLE_HASH('l', 'S'): + /* operator <<= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "<<=", 3)); + + case SIMPLE_HASH('l', 't'): + /* operator < */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "<", 1)); + + case SIMPLE_HASH('m', 'i'): + /* operator - */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "-", 1)); + + case SIMPLE_HASH('m', 'I'): + /* operator -= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "-=", 2)); + + case SIMPLE_HASH('m', 'l'): + /* operator * */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "*", 1)); + + case SIMPLE_HASH('m', 'L'): + /* operator *= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "*=", 2)); + + case SIMPLE_HASH('m', 'm'): + /* operator -- */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "--", 2)); + + case SIMPLE_HASH('n', 'a'): + /* operator new[] */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "new []", 6)); + + case SIMPLE_HASH('n', 'e'): + /* operator != */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "!=", 2)); + + case SIMPLE_HASH('n', 'g'): + /* operator - (unary) */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "-", 1)); + + case SIMPLE_HASH('n', 't'): + /* operator ! */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "!", 1)); + + case SIMPLE_HASH('n', 'w'): + /* operator new */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "new", 3)); + + case SIMPLE_HASH('o', 'o'): + /* operator || */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "||", 2)); + + case SIMPLE_HASH('o', 'r'): + /* operator | */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "|", 1)); + + case SIMPLE_HASH('o', 'R'): + /* operator |= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "|=", 2)); + + case SIMPLE_HASH('p', 'l'): + /* operator + */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "+", 1)); + + case SIMPLE_HASH('p', 'L'): + /* operator += */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "+=", 2)); + + case SIMPLE_HASH('p', 'm'): + /* operator ->* */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "->*", 3)); + + case SIMPLE_HASH('p', 'p'): + /* operator ++ */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "++", 2)); + + case SIMPLE_HASH('p', 's'): + /* operator + (unary) */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "+", 1)); + + case SIMPLE_HASH('p', 't'): + /* operator -> */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "->", 2)); + + case SIMPLE_HASH('q', 'u'): + /* operator ? */ + ddata->cur += 2; + return (cpp_demangle_read_expression_trinary(ddata, "?", 1, + ":", 1)); + + case SIMPLE_HASH('r', 'm'): + /* operator % */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "%", 1)); + + case SIMPLE_HASH('r', 'M'): + /* operator %= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, "%=", 2)); + + case SIMPLE_HASH('r', 's'): + /* operator >> */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, ">>", 2)); + + case SIMPLE_HASH('r', 'S'): + /* operator >>= */ + ddata->cur += 2; + return (cpp_demangle_read_expression_binary(ddata, ">>=", 3)); + + case SIMPLE_HASH('r', 'z'): + /* operator sizeof */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6)); + + case SIMPLE_HASH('s', 'v'): + /* operator sizeof */ + ddata->cur += 2; + return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6)); + }; + + switch (*ddata->cur) { + case 'L': + return (cpp_demangle_read_expr_primary(ddata)); + case 'T': + return (cpp_demangle_read_tmpl_param(ddata)); + }; + + return (0); +} + +static int +cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata, + const char *name, size_t len) +{ + + if (ddata == NULL || name == NULL || len == 0) + return (0); + if (!cpp_demangle_read_expression(ddata)) + return (0); + if (!cpp_demangle_push_str(ddata, name, len)) + return (0); + + return (cpp_demangle_read_expression(ddata)); +} + +static int +cpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata, + const char *name, size_t len) +{ + + if (ddata == NULL || name == NULL || len == 0) + return (0); + if (!cpp_demangle_read_expression(ddata)) + return (0); + + return (cpp_demangle_push_str(ddata, name, len)); +} + +static int +cpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata, + const char *name1, size_t len1, const char *name2, size_t len2) +{ + + if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL || + len2 == 0) + return (0); + + if (!cpp_demangle_read_expression(ddata)) + return (0); + if (!cpp_demangle_push_str(ddata, name1, len1)) + return (0); + if (!cpp_demangle_read_expression(ddata)) + return (0); + if (!cpp_demangle_push_str(ddata, name2, len2)) + return (0); + + return (cpp_demangle_read_expression(ddata)); +} + +static int +cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, + struct vector_type_qualifier *v) +{ + size_t class_type_size, class_type_len, limit; + const char *class_type; + + if (ddata == NULL || *ddata->cur != 'F' || v == NULL) + return (0); + + ++ddata->cur; + if (*ddata->cur == 'Y') { + if (ext_c != NULL) + *ext_c = 1; + ++ddata->cur; + } + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + if (*ddata->cur != 'E') { + if (!cpp_demangle_push_str(ddata, "(", 1)) + return (0); + if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) { + if ((class_type_size = ddata->class_type.size) == 0) + return (0); + class_type = + ddata->class_type.container[class_type_size - 1]; + if (class_type == NULL) + return (0); + if ((class_type_len = strlen(class_type)) == 0) + return (0); + if (!cpp_demangle_push_str(ddata, class_type, + class_type_len)) + return (0); + if (!cpp_demangle_push_str(ddata, "::*", 3)) + return (0); + ++ddata->func_type; + } else { + if (!cpp_demangle_push_type_qualifier(ddata, v, + (const char *) NULL)) + return (0); + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + } + + if (!cpp_demangle_push_str(ddata, ")(", 2)) + return (0); + + limit = 0; + for (;;) { + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + if (*ddata->cur == 'E') + break; + if (limit++ > CPP_DEMANGLE_TRY_LIMIT) + return (0); + } + + if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) { + if (!cpp_demangle_push_type_qualifier(ddata, v, + (const char *) NULL)) + return (0); + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + } + + if (!cpp_demangle_push_str(ddata, ")", 1)) + return (0); + } + + ++ddata->cur; + + return (1); +} + +/* read encoding, encoding are function name, data name, special-name */ +static int +cpp_demangle_read_encoding(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + /* special name */ + switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('G', 'V'): + /* sentry object for 1 time init */ + if (!cpp_demangle_push_str(ddata, "guard variable for ", 20)) + return (0); + ddata->cur += 2; + break; + + case SIMPLE_HASH('T', 'c'): + /* virtual function covariant override thunk */ + if (!cpp_demangle_push_str(ddata, + "virtual function covariant override ", 36)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_offset(ddata)) + return (0); + if (!cpp_demangle_read_offset(ddata)) + return (0); + return (cpp_demangle_read_encoding(ddata)); + + case SIMPLE_HASH('T', 'D'): + /* typeinfo common proxy */ + break; + + case SIMPLE_HASH('T', 'h'): + /* virtual function non-virtual override thunk */ + if (cpp_demangle_push_str(ddata, + "virtual function non-virtual override ", 38) == 0) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_nv_offset(ddata)) + return (0); + return (cpp_demangle_read_encoding(ddata)); + + case SIMPLE_HASH('T', 'I'): + /* typeinfo structure */ + /* FALLTHROUGH */ + case SIMPLE_HASH('T', 'S'): + /* RTTI name (NTBS) */ + if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 1)); + + case SIMPLE_HASH('T', 'T'): + /* VTT table */ + if (!cpp_demangle_push_str(ddata, "VTT for ", 8)) + return (0); + ddata->cur += 2; + return (cpp_demangle_read_type(ddata, 1)); + + case SIMPLE_HASH('T', 'v'): + /* virtual function virtual override thunk */ + if (!cpp_demangle_push_str(ddata, + "virtual function virtual override ", 34)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + if (!cpp_demangle_read_v_offset(ddata)) + return (0); + return (cpp_demangle_read_encoding(ddata)); + + case SIMPLE_HASH('T', 'V'): + /* virtual table */ + if (!cpp_demangle_push_str(ddata, "vtable for ", 12)) + return (0); + ddata->cur += 2; + if (*ddata->cur == '\0') + return (0); + return (cpp_demangle_read_type(ddata, 1)); + }; + + return (cpp_demangle_read_name(ddata)); +} + +static int +cpp_demangle_read_local_name(struct cpp_demangle_data *ddata) +{ + size_t limit; + + if (ddata == NULL) + return (0); + if (*(++ddata->cur) == '\0') + return (0); + if (!cpp_demangle_read_encoding(ddata)) + return (0); + + limit = 0; + for (;;) { + if (!cpp_demangle_read_type(ddata, 1)) + return (0); + if (*ddata->cur == 'E') + break; + if (limit++ > CPP_DEMANGLE_TRY_LIMIT) + return (0); + } + if (*(++ddata->cur) == '\0') + return (0); + if (ddata->paren == true) { + if (!cpp_demangle_push_str(ddata, ")", 1)) + return (0); + ddata->paren = false; + } + if (*ddata->cur == 's') + ++ddata->cur; + else { + if (!cpp_demangle_push_str(ddata, "::", 2)) + return (0); + if (!cpp_demangle_read_name(ddata)) + return (0); + } + if (*ddata->cur == '_') { + ++ddata->cur; + while (ELFTC_ISDIGIT(*ddata->cur) != 0) + ++ddata->cur; + } + + return (1); +} + +static int +cpp_demangle_read_name(struct cpp_demangle_data *ddata) +{ + struct vector_str *output, v; + size_t p_idx, subst_str_len; + int rtn; + char *subst_str; + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + output = cpp_demangle_gnu3_push_head > 0 ? + &ddata->output_tmp : &ddata->output; + + subst_str = NULL; + + switch (*ddata->cur) { + case 'S': + return (cpp_demangle_read_subst(ddata)); + case 'N': + return (cpp_demangle_read_nested_name(ddata)); + case 'Z': + return (cpp_demangle_read_local_name(ddata)); + }; + + if (!vector_str_init(&v)) + return (0); + + p_idx = output->size; + rtn = 0; + if (!cpp_demangle_read_uqname(ddata)) + goto clean; + if ((subst_str = vector_str_substr(output, p_idx, output->size - 1, + &subst_str_len)) == NULL) + goto clean; + if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) { + rtn = 1; + goto clean; + } + if (!vector_str_push(&v, subst_str, subst_str_len)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &v)) + goto clean; + + if (*ddata->cur == 'I') { + p_idx = output->size; + if (!cpp_demangle_read_tmpl_args(ddata)) + goto clean; + free(subst_str); + if ((subst_str = vector_str_substr(output, p_idx, + output->size - 1, &subst_str_len)) == NULL) + goto clean; + if (!vector_str_push(&v, subst_str, subst_str_len)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &v)) + goto clean; + } + + rtn = 1; + +clean: + free(subst_str); + vector_str_dest(&v); + + return (rtn); +} + +static int +cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata) +{ + struct vector_str *output, v; + size_t limit, p_idx, subst_str_len; + int rtn; + char *subst_str; + + if (ddata == NULL || *ddata->cur != 'N') + return (0); + if (*(++ddata->cur) == '\0') + return (0); + + while (*ddata->cur == 'r' || *ddata->cur == 'V' || + *ddata->cur == 'K') { + switch (*ddata->cur) { + case 'r': + ddata->mem_rst = true; + break; + case 'V': + ddata->mem_vat = true; + break; + case 'K': + ddata->mem_cst = true; + break; + }; + ++ddata->cur; + } + + output = cpp_demangle_gnu3_push_head > 0 ? + &ddata->output_tmp : &ddata->output; + if (!vector_str_init(&v)) + return (0); + + rtn = 0; + limit = 0; + for (;;) { + p_idx = output->size; + switch (*ddata->cur) { + case 'I': + if (!cpp_demangle_read_tmpl_args(ddata)) + goto clean; + break; + case 'S': + if (!cpp_demangle_read_subst(ddata)) + goto clean; + break; + case 'T': + if (!cpp_demangle_read_tmpl_param(ddata)) + goto clean; + break; + default: + if (!cpp_demangle_read_uqname(ddata)) + goto clean; + }; + + if ((subst_str = vector_str_substr(output, p_idx, + output->size - 1, &subst_str_len)) == NULL) + goto clean; + if (!vector_str_push(&v, subst_str, subst_str_len)) { + free(subst_str); + goto clean; + } + free(subst_str); + + if (!cpp_demangle_push_subst_v(ddata, &v)) + goto clean; + if (*ddata->cur == 'E') + break; + else if (*ddata->cur != 'I' && + *ddata->cur != 'C' && *ddata->cur != 'D') { + if (!cpp_demangle_push_str(ddata, "::", 2)) + goto clean; + if (!vector_str_push(&v, "::", 2)) + goto clean; + } + if (limit++ > CPP_DEMANGLE_TRY_LIMIT) + goto clean; + } + + ++ddata->cur; + rtn = 1; + +clean: + vector_str_dest(&v); + + return (rtn); +} + +/* + * read number + * number ::= [n] + */ +static int +cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn) +{ + long len, negative_factor; + + if (ddata == NULL || rtn == NULL) + return (0); + + negative_factor = 1; + if (*ddata->cur == 'n') { + negative_factor = -1; + + ++ddata->cur; + } + if (ELFTC_ISDIGIT(*ddata->cur) == 0) + return (0); + + errno = 0; + if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 && + errno != 0) + return (0); + + while (ELFTC_ISDIGIT(*ddata->cur) != 0) + ++ddata->cur; + + assert(len >= 0); + assert(negative_factor == 1 || negative_factor == -1); + + *rtn = len * negative_factor; + + return (1); +} + +static int +cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL) + return (0); + + if (!cpp_demangle_push_str(ddata, "offset : ", 9)) + return (0); + + return (cpp_demangle_read_offset_number(ddata)); +} + +/* read offset, offset are nv-offset, v-offset */ +static int +cpp_demangle_read_offset(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL) + return (0); + + if (*ddata->cur == 'h') { + ++ddata->cur; + return (cpp_demangle_read_nv_offset(ddata)); + } else if (*ddata->cur == 'v') { + ++ddata->cur; + return (cpp_demangle_read_v_offset(ddata)); + } + + return (0); +} + +static int +cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata) +{ + bool negative; + const char *start; + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + /* offset could be negative */ + if (*ddata->cur == 'n') { + negative = true; + start = ddata->cur + 1; + } else { + negative = false; + start = ddata->cur; + } + + while (*ddata->cur != '_') + ++ddata->cur; + + if (negative && !cpp_demangle_push_str(ddata, "-", 1)) + return (0); + + assert(start != NULL); + + if (!cpp_demangle_push_str(ddata, start, ddata->cur - start)) + return (0); + if (!cpp_demangle_push_str(ddata, " ", 1)) + return (0); + + ++ddata->cur; + + return (1); +} + +static int +cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata) +{ + size_t class_type_len, i, idx, p_idx; + int p_func_type, rtn; + char *class_type; + + if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0') + return (0); + + p_idx = ddata->output.size; + if (!cpp_demangle_read_type(ddata, 0)) + return (0); + + if ((class_type = vector_str_substr(&ddata->output, p_idx, + ddata->output.size - 1, &class_type_len)) == NULL) + return (0); + + rtn = 0; + idx = ddata->output.size; + for (i = p_idx; i < idx; ++i) + if (!vector_str_pop(&ddata->output)) + goto clean1; + + if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM)) + goto clean1; + + if (!vector_str_push(&ddata->class_type, class_type, class_type_len)) + goto clean2; + + p_func_type = ddata->func_type; + if (!cpp_demangle_read_type(ddata, 0)) + goto clean3; + + if (p_func_type == ddata->func_type) { + if (!cpp_demangle_push_str(ddata, " ", 1)) + goto clean3; + if (!cpp_demangle_push_str(ddata, class_type, class_type_len)) + goto clean3; + if (!cpp_demangle_push_str(ddata, "::*", 3)) + goto clean3; + } + + rtn = 1; +clean3: + if (!vector_str_pop(&ddata->class_type)) + rtn = 0; +clean2: + if (!vector_read_cmd_pop(&ddata->cmd)) + rtn = 0; +clean1: + free(class_type); + + return (rtn); +} + +/* read source-name, source-name is */ +static int +cpp_demangle_read_sname(struct cpp_demangle_data *ddata) +{ + long len; + + if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 || + len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0) + return (0); + + assert(ddata->output.size > 0); + if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0) + ddata->last_sname = + ddata->output.container[ddata->output.size - 1]; + + ddata->cur += len; + + return (1); +} + +static int +cpp_demangle_read_subst(struct cpp_demangle_data *ddata) +{ + long nth; + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + /* abbreviations of the form Sx */ + switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('S', 'a'): + /* std::allocator */ + if (cpp_demangle_push_str(ddata, "std::allocator", 14) == 0) + return (0); + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::allocator", 14)); + return (1); + + case SIMPLE_HASH('S', 'b'): + /* std::basic_string */ + if (!cpp_demangle_push_str(ddata, "std::basic_string", 17)) + return (0); + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::basic_string", 17)); + return (1); + + case SIMPLE_HASH('S', 'd'): + /* std::basic_iostream > */ + if (!cpp_demangle_push_str(ddata, "std::iostream", 19)) + return (0); + ddata->last_sname = "iostream"; + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::iostream", 19)); + return (1); + + case SIMPLE_HASH('S', 'i'): + /* std::basic_istream > */ + if (!cpp_demangle_push_str(ddata, "std::istream", 18)) + return (0); + ddata->last_sname = "istream"; + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::istream", 18)); + return (1); + + case SIMPLE_HASH('S', 'o'): + /* std::basic_ostream > */ + if (!cpp_demangle_push_str(ddata, "std::ostream", 18)) + return (0); + ddata->last_sname = "istream"; + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::ostream", 18)); + return (1); + + case SIMPLE_HASH('S', 's'): + /* + * std::basic_string, + * std::allocator > + * + * a.k.a std::string + */ + if (!cpp_demangle_push_str(ddata, "std::string", 11)) + return (0); + ddata->last_sname = "string"; + ddata->cur += 2; + if (*ddata->cur == 'I') + return (cpp_demangle_read_subst_stdtmpl(ddata, + "std::string", 11)); + return (1); + + case SIMPLE_HASH('S', 't'): + /* std:: */ + return (cpp_demangle_read_subst_std(ddata)); + }; + + if (*(++ddata->cur) == '\0') + return (0); + + /* substitution */ + if (*ddata->cur == '_') + return (cpp_demangle_get_subst(ddata, 0)); + else { + errno = 0; + /* substitution number is base 36 */ + if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 && + errno != 0) + return (0); + + /* first was '_', so increase one */ + ++nth; + + while (*ddata->cur != '_') + ++ddata->cur; + + assert(nth > 0); + + return (cpp_demangle_get_subst(ddata, nth)); + } + + /* NOTREACHED */ + return (0); +} + +static int +cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata) +{ + struct vector_str *output, v; + size_t p_idx, subst_str_len; + int rtn; + char *subst_str; + + if (ddata == NULL) + return (0); + + if (!vector_str_init(&v)) + return (0); + + subst_str = NULL; + rtn = 0; + if (!cpp_demangle_push_str(ddata, "std::", 5)) + goto clean; + + if (!vector_str_push(&v, "std::", 5)) + goto clean; + + ddata->cur += 2; + + output = cpp_demangle_gnu3_push_head > 0 ? + &ddata->output_tmp : &ddata->output; + + p_idx = output->size; + if (!cpp_demangle_read_uqname(ddata)) + goto clean; + + if ((subst_str = vector_str_substr(output, p_idx, output->size - 1, + &subst_str_len)) == NULL) + goto clean; + + if (!vector_str_push(&v, subst_str, subst_str_len)) + goto clean; + + if (!cpp_demangle_push_subst_v(ddata, &v)) + goto clean; + + if (*ddata->cur == 'I') { + p_idx = output->size; + if (!cpp_demangle_read_tmpl_args(ddata)) + goto clean; + free(subst_str); + if ((subst_str = vector_str_substr(output, p_idx, + output->size - 1, &subst_str_len)) == NULL) + goto clean; + if (!vector_str_push(&v, subst_str, subst_str_len)) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, &v)) + goto clean; + } + + rtn = 1; +clean: + free(subst_str); + vector_str_dest(&v); + + return (rtn); +} + +static int +cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata, + const char *str, size_t len) +{ + struct vector_str *output; + size_t p_idx, substr_len; + int rtn; + char *subst_str, *substr; + + if (ddata == NULL || str == NULL || len == 0) + return (0); + + output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp : + &ddata->output; + + p_idx = output->size; + substr = NULL; + subst_str = NULL; + + if (!cpp_demangle_read_tmpl_args(ddata)) + return (0); + if ((substr = vector_str_substr(output, p_idx, output->size - 1, + &substr_len)) == NULL) + return (0); + + rtn = 0; + if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) == + NULL) + goto clean; + + memcpy(subst_str, str, len); + memcpy(subst_str + len, substr, substr_len); + subst_str[substr_len + len] = '\0'; + + if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len)) + goto clean; + + rtn = 1; +clean: + free(subst_str); + free(substr); + + return (rtn); +} + +static int +cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + switch (*ddata->cur) { + case 'L': + return (cpp_demangle_read_expr_primary(ddata)); + case 'X': + return (cpp_demangle_read_expression(ddata)); + }; + + return (cpp_demangle_read_type(ddata, 0)); +} + +static int +cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata) +{ + struct vector_str *v; + size_t arg_len, idx, limit, size; + char *arg; + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + ++ddata->cur; + + if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL)) + return (0); + + if (!cpp_demangle_push_str(ddata, "<", 1)) + return (0); + + limit = 0; + v = cpp_demangle_gnu3_push_head > 0 ? + &ddata->output_tmp : &ddata->output; + for (;;) { + idx = v->size; + if (!cpp_demangle_read_tmpl_arg(ddata)) + return (0); + if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) == + NULL) + return (0); + if (!vector_str_find(&ddata->tmpl, arg, arg_len) && + !vector_str_push(&ddata->tmpl, arg, arg_len)) { + free(arg); + return (0); + } + + free(arg); + + if (*ddata->cur == 'E') { + ++ddata->cur; + size = v->size; + assert(size > 0); + if (!strncmp(v->container[size - 1], ">", 1)) { + if (!cpp_demangle_push_str(ddata, " >", 2)) + return (0); + } else if (!cpp_demangle_push_str(ddata, ">", 1)) + return (0); + break; + } else if (*ddata->cur != 'I' && + !cpp_demangle_push_str(ddata, ", ", 2)) + return (0); + + if (limit++ > CPP_DEMANGLE_TRY_LIMIT) + return (0); + } + + return (vector_read_cmd_pop(&ddata->cmd)); +} + +/* + * Read template parameter that forms in 'T[number]_'. + * This function much like to read_subst but only for types. + */ +static int +cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata) +{ + long nth; + + if (ddata == NULL || *ddata->cur != 'T') + return (0); + + ++ddata->cur; + + if (*ddata->cur == '_') + return (cpp_demangle_get_tmpl_param(ddata, 0)); + else { + + errno = 0; + if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 && + errno != 0) + return (0); + + /* T_ is first */ + ++nth; + + while (*ddata->cur != '_') + ++ddata->cur; + + assert(nth > 0); + + return (cpp_demangle_get_tmpl_param(ddata, nth)); + } + + /* NOTREACHED */ + return (0); +} + +static int +cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) +{ + struct vector_type_qualifier v; + struct vector_str *output; + size_t p_idx, type_str_len; + int extern_c, is_builtin; + long len; + char *type_str; + + if (ddata == NULL) + return (0); + + output = &ddata->output; + if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) { + cpp_demangle_gnu3_push_head++; + output = &ddata->output_tmp; + } else if (delimit == 1) { + if (ddata->paren == false) { + if (!cpp_demangle_push_str(ddata, "(", 1)) + return (0); + if (ddata->output.size < 2) + return (0); + ddata->paren = true; + ddata->pfirst = true; + /* Need pop function name */ + if (ddata->subst.size == 1 && + !vector_str_pop(&ddata->subst)) + return (0); + } + + if (ddata->pfirst) + ddata->pfirst = false; + else if (*ddata->cur != 'I' && + !cpp_demangle_push_str(ddata, ", ", 2)) + return (0); + } + + assert(output != NULL); + /* + * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array + * pointer-to-member, template-param, template-template-param, subst + */ + + if (!vector_type_qualifier_init(&v)) + return (0); + + extern_c = 0; + is_builtin = 1; + p_idx = output->size; + type_str = NULL; +again: + /* builtin type */ + switch (*ddata->cur) { + case 'a': + /* signed char */ + if (!cpp_demangle_push_str(ddata, "signed char", 11)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'A': + /* array type */ + if (!cpp_demangle_read_array(ddata)) + goto clean; + is_builtin = 0; + goto rtn; + + case 'b': + /* bool */ + if (!cpp_demangle_push_str(ddata, "bool", 4)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'C': + /* complex pair */ + if (!vector_type_qualifier_push(&v, TYPE_CMX)) + goto clean; + ++ddata->cur; + goto again; + + case 'c': + /* char */ + if (!cpp_demangle_push_str(ddata, "char", 4)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'd': + /* double */ + if (!cpp_demangle_push_str(ddata, "double", 6)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'e': + /* long double */ + if (!cpp_demangle_push_str(ddata, "long double", 11)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'f': + /* float */ + if (!cpp_demangle_push_str(ddata, "float", 5)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'F': + /* function */ + if (!cpp_demangle_read_function(ddata, &extern_c, &v)) + goto clean; + is_builtin = 0; + goto rtn; + + case 'g': + /* __float128 */ + if (!cpp_demangle_push_str(ddata, "__float128", 10)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'G': + /* imaginary */ + if (!vector_type_qualifier_push(&v, TYPE_IMG)) + goto clean; + ++ddata->cur; + goto again; + + case 'h': + /* unsigned char */ + if (!cpp_demangle_push_str(ddata, "unsigned char", 13)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'i': + /* int */ + if (!cpp_demangle_push_str(ddata, "int", 3)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'j': + /* unsigned int */ + if (!cpp_demangle_push_str(ddata, "unsigned int", 12)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'K': + /* const */ + if (!vector_type_qualifier_push(&v, TYPE_CST)) + goto clean; + ++ddata->cur; + goto again; + + case 'l': + /* long */ + if (!cpp_demangle_push_str(ddata, "long", 4)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'm': + /* unsigned long */ + if (!cpp_demangle_push_str(ddata, "unsigned long", 13)) + goto clean; + + ++ddata->cur; + + goto rtn; + case 'M': + /* pointer to member */ + if (!cpp_demangle_read_pointer_to_member(ddata)) + goto clean; + is_builtin = 0; + goto rtn; + + case 'n': + /* __int128 */ + if (!cpp_demangle_push_str(ddata, "__int128", 8)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'o': + /* unsigned __int128 */ + if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'P': + /* pointer */ + if (!vector_type_qualifier_push(&v, TYPE_PTR)) + goto clean; + ++ddata->cur; + goto again; + + case 'r': + /* restrict */ + if (!vector_type_qualifier_push(&v, TYPE_RST)) + goto clean; + ++ddata->cur; + goto again; + + case 'R': + /* reference */ + if (!vector_type_qualifier_push(&v, TYPE_REF)) + goto clean; + ++ddata->cur; + goto again; + + case 's': + /* short, local string */ + if (!cpp_demangle_push_str(ddata, "short", 5)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'S': + /* substitution */ + if (!cpp_demangle_read_subst(ddata)) + goto clean; + is_builtin = 0; + goto rtn; + + case 't': + /* unsigned short */ + if (!cpp_demangle_push_str(ddata, "unsigned short", 14)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'T': + /* template parameter */ + if (!cpp_demangle_read_tmpl_param(ddata)) + goto clean; + is_builtin = 0; + goto rtn; + + case 'u': + /* vendor extended builtin */ + ++ddata->cur; + if (!cpp_demangle_read_sname(ddata)) + goto clean; + is_builtin = 0; + goto rtn; + + case 'U': + /* vendor extended type qualifier */ + if (!cpp_demangle_read_number(ddata, &len)) + goto clean; + if (len <= 0) + goto clean; + if (!vector_str_push(&v.ext_name, ddata->cur, len)) + return (0); + ddata->cur += len; + goto again; + + case 'v': + /* void */ + if (!cpp_demangle_push_str(ddata, "void", 4)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'V': + /* volatile */ + if (!vector_type_qualifier_push(&v, TYPE_VAT)) + goto clean; + ++ddata->cur; + goto again; + + case 'w': + /* wchar_t */ + if (!cpp_demangle_push_str(ddata, "wchar_t", 6)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'x': + /* long long */ + if (!cpp_demangle_push_str(ddata, "long long", 9)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'y': + /* unsigned long long */ + if (!cpp_demangle_push_str(ddata, "unsigned long long", 18)) + goto clean; + ++ddata->cur; + goto rtn; + + case 'z': + /* ellipsis */ + if (!cpp_demangle_push_str(ddata, "ellipsis", 8)) + goto clean; + ++ddata->cur; + goto rtn; + }; + + if (!cpp_demangle_read_name(ddata)) + goto clean; + + is_builtin = 0; +rtn: + if ((type_str = vector_str_substr(output, p_idx, output->size - 1, + &type_str_len)) == NULL) + goto clean; + + if (is_builtin == 0) { + if (!vector_str_find(&ddata->subst, type_str, type_str_len) && + !vector_str_push(&ddata->subst, type_str, type_str_len)) + goto clean; + } + + if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str)) + goto clean; + + free(type_str); + vector_type_qualifier_dest(&v); + + if (cpp_demangle_gnu3_push_head > 0) { + if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata) + == 0) + return (0); + + if (--cpp_demangle_gnu3_push_head > 0) + return (1); + + if (!vector_str_push(&ddata->output_tmp, " ", 1)) + return (0); + + if (!vector_str_push_vector_head(&ddata->output, + &ddata->output_tmp)) + return (0); + + vector_str_dest(&ddata->output_tmp); + if (!vector_str_init(&ddata->output_tmp)) + return (0); + + if (!cpp_demangle_push_str(ddata, "(", 1)) + return (0); + + ddata->paren = true; + ddata->pfirst = true; + } + + return (1); +clean: + free(type_str); + vector_type_qualifier_dest(&v); + + return (0); +} + +/* + * read unqualified-name, unqualified name are operator-name, ctor-dtor-name, + * source-name + */ +static int +cpp_demangle_read_uqname(struct cpp_demangle_data *ddata) +{ + size_t len; + + if (ddata == NULL || *ddata->cur == '\0') + return (0); + + /* operator name */ + switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('a', 'a'): + /* operator && */ + if (!cpp_demangle_push_str(ddata, "operator&&", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('a', 'd'): + /* operator & (unary) */ + if (!cpp_demangle_push_str(ddata, "operator&", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('a', 'n'): + /* operator & */ + if (!cpp_demangle_push_str(ddata, "operator&", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('a', 'N'): + /* operator &= */ + if (!cpp_demangle_push_str(ddata, "operator&=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('a', 'S'): + /* operator = */ + if (!cpp_demangle_push_str(ddata, "operator=", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('c', 'l'): + /* operator () */ + if (!cpp_demangle_push_str(ddata, "operator()", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('c', 'm'): + /* operator , */ + if (!cpp_demangle_push_str(ddata, "operator,", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('c', 'o'): + /* operator ~ */ + if (!cpp_demangle_push_str(ddata, "operator~", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('c', 'v'): + /* operator (cast) */ + if (!cpp_demangle_push_str(ddata, "operator(cast)", 14)) + return (0); + ddata->cur += 2; + return (cpp_demangle_read_type(ddata, 1)); + + case SIMPLE_HASH('d', 'a'): + /* operator delete [] */ + if (!cpp_demangle_push_str(ddata, "operator delete []", 18)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('d', 'e'): + /* operator * (unary) */ + if (!cpp_demangle_push_str(ddata, "operator*", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('d', 'l'): + /* operator delete */ + if (!cpp_demangle_push_str(ddata, "operator delete", 15)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('d', 'v'): + /* operator / */ + if (!cpp_demangle_push_str(ddata, "operator/", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('d', 'V'): + /* operator /= */ + if (!cpp_demangle_push_str(ddata, "operator/=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('e', 'o'): + /* operator ^ */ + if (!cpp_demangle_push_str(ddata, "operator^", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('e', 'O'): + /* operator ^= */ + if (!cpp_demangle_push_str(ddata, "operator^=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('e', 'q'): + /* operator == */ + if (!cpp_demangle_push_str(ddata, "operator==", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('g', 'e'): + /* operator >= */ + if (!cpp_demangle_push_str(ddata, "operator>=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('g', 't'): + /* operator > */ + if (!cpp_demangle_push_str(ddata, "operator>", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('i', 'x'): + /* operator [] */ + if (!cpp_demangle_push_str(ddata, "operator[]", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('l', 'e'): + /* operator <= */ + if (!cpp_demangle_push_str(ddata, "operator<=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('l', 's'): + /* operator << */ + if (!cpp_demangle_push_str(ddata, "operator<<", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('l', 'S'): + /* operator <<= */ + if (!cpp_demangle_push_str(ddata, "operator<<=", 11)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('l', 't'): + /* operator < */ + if (!cpp_demangle_push_str(ddata, "operator<", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('m', 'i'): + /* operator - */ + if (!cpp_demangle_push_str(ddata, "operator-", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('m', 'I'): + /* operator -= */ + if (!cpp_demangle_push_str(ddata, "operator-=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('m', 'l'): + /* operator * */ + if (!cpp_demangle_push_str(ddata, "operator*", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('m', 'L'): + /* operator *= */ + if (!cpp_demangle_push_str(ddata, "operator*=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('m', 'm'): + /* operator -- */ + if (!cpp_demangle_push_str(ddata, "operator--", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('n', 'a'): + /* operator new[] */ + if (!cpp_demangle_push_str(ddata, "operator new []", 15)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('n', 'e'): + /* operator != */ + if (!cpp_demangle_push_str(ddata, "operator!=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('n', 'g'): + /* operator - (unary) */ + if (!cpp_demangle_push_str(ddata, "operator-", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('n', 't'): + /* operator ! */ + if (!cpp_demangle_push_str(ddata, "operator!", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('n', 'w'): + /* operator new */ + if (!cpp_demangle_push_str(ddata, "operator new", 12)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('o', 'o'): + /* operator || */ + if (!cpp_demangle_push_str(ddata, "operator||", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('o', 'r'): + /* operator | */ + if (!cpp_demangle_push_str(ddata, "operator|", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('o', 'R'): + /* operator |= */ + if (!cpp_demangle_push_str(ddata, "operator|=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 'l'): + /* operator + */ + if (!cpp_demangle_push_str(ddata, "operator+", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 'L'): + /* operator += */ + if (!cpp_demangle_push_str(ddata, "operator+=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 'm'): + /* operator ->* */ + if (!cpp_demangle_push_str(ddata, "operator->*", 11)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 'p'): + /* operator ++ */ + if (!cpp_demangle_push_str(ddata, "operator++", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 's'): + /* operator + (unary) */ + if (!cpp_demangle_push_str(ddata, "operator+", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('p', 't'): + /* operator -> */ + if (!cpp_demangle_push_str(ddata, "operator->", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('q', 'u'): + /* operator ? */ + if (!cpp_demangle_push_str(ddata, "operator?", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('r', 'm'): + /* operator % */ + if (!cpp_demangle_push_str(ddata, "operator%", 9)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('r', 'M'): + /* operator %= */ + if (!cpp_demangle_push_str(ddata, "operator%=", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('r', 's'): + /* operator >> */ + if (!cpp_demangle_push_str(ddata, "operator>>", 10)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('r', 'S'): + /* operator >>= */ + if (!cpp_demangle_push_str(ddata, "operator>>=", 11)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('r', 'z'): + /* operator sizeof */ + if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('s', 'r'): + /* scope resolution operator */ + if (!cpp_demangle_push_str(ddata, "scope resolution operator ", + 26)) + return (0); + ddata->cur += 2; + return (1); + + case SIMPLE_HASH('s', 'v'): + /* operator sizeof */ + if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16)) + return (0); + ddata->cur += 2; + return (1); + }; + + /* vendor extened operator */ + if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) { + if (!cpp_demangle_push_str(ddata, "vendor extened operator ", + 24)) + return (0); + if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1)) + return (0); + ddata->cur += 2; + return (cpp_demangle_read_sname(ddata)); + } + + /* ctor-dtor-name */ + switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { + case SIMPLE_HASH('C', '1'): + /* FALLTHROUGH */ + case SIMPLE_HASH('C', '2'): + /* FALLTHROUGH */ + case SIMPLE_HASH('C', '3'): + if (ddata->last_sname == NULL) + return (0); + if ((len = strlen(ddata->last_sname)) == 0) + return (0); + if (!cpp_demangle_push_str(ddata, "::", 2)) + return (0); + if (!cpp_demangle_push_str(ddata, ddata->last_sname, len)) + return (0); + ddata->cur +=2; + return (1); + + case SIMPLE_HASH('D', '0'): + /* FALLTHROUGH */ + case SIMPLE_HASH('D', '1'): + /* FALLTHROUGH */ + case SIMPLE_HASH('D', '2'): + if (ddata->last_sname == NULL) + return (0); + if ((len = strlen(ddata->last_sname)) == 0) + return (0); + if (!cpp_demangle_push_str(ddata, "::~", 3)) + return (0); + if (!cpp_demangle_push_str(ddata, ddata->last_sname, len)) + return (0); + ddata->cur +=2; + return (1); + }; + + /* source name */ + if (ELFTC_ISDIGIT(*ddata->cur) != 0) + return (cpp_demangle_read_sname(ddata)); + + /* local source name */ + if (*ddata->cur == 'L') + return (cpp_demangle_local_source_name(ddata)); + + return (1); +} + +/* + * Read local source name. + * + * References: + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 + * http://gcc.gnu.org/viewcvs?view=rev&revision=124467 + */ +static int +cpp_demangle_local_source_name(struct cpp_demangle_data *ddata) +{ + /* L */ + if (ddata == NULL || *ddata->cur != 'L') + return (0); + ++ddata->cur; + + /* source name */ + if (!cpp_demangle_read_sname(ddata)) + return (0); + + /* discriminator */ + if (*ddata->cur == '_') { + ++ddata->cur; + while (ELFTC_ISDIGIT(*ddata->cur) != 0) + ++ddata->cur; + } + + return (1); +} + +static int +cpp_demangle_read_v_offset(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL) + return (0); + + if (!cpp_demangle_push_str(ddata, "offset : ", 9)) + return (0); + + if (!cpp_demangle_read_offset_number(ddata)) + return (0); + + if (!cpp_demangle_push_str(ddata, "virtual offset : ", 17)) + return (0); + + return (!cpp_demangle_read_offset_number(ddata)); +} + +/* + * Decode floating point representation to string + * Return new allocated string or NULL + * + * Todo + * Replace these functions to macro. + */ +static char * +decode_fp_to_double(const char *p, size_t len) +{ + double f; + size_t rtn_len, limit, i; + int byte; + char *rtn; + + if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double)) + return (NULL); + + memset(&f, 0, sizeof(double)); + + for (i = 0; i < len / 2; ++i) { + byte = hex_to_dec(p[len - i * 2 - 1]) + + hex_to_dec(p[len - i * 2 - 2]) * 16; + + if (byte < 0 || byte > 255) + return (NULL); + +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + ((unsigned char *)&f)[i] = (unsigned char)(byte); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + ((unsigned char *)&f)[sizeof(double) - i - 1] = + (unsigned char)(byte); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + } + + rtn_len = 64; + limit = 0; +again: + if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL) + return (NULL); + + if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) { + free(rtn); + if (limit++ > FLOAT_SPRINTF_TRY_LIMIT) + return (NULL); + rtn_len *= BUFFER_GROWFACTOR; + goto again; + } + + return rtn; +} + +static char * +decode_fp_to_float(const char *p, size_t len) +{ + size_t i, rtn_len, limit; + float f; + int byte; + char *rtn; + + if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float)) + return (NULL); + + memset(&f, 0, sizeof(float)); + + for (i = 0; i < len / 2; ++i) { + byte = hex_to_dec(p[len - i * 2 - 1]) + + hex_to_dec(p[len - i * 2 - 2]) * 16; + if (byte < 0 || byte > 255) + return (NULL); +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + ((unsigned char *)&f)[i] = (unsigned char)(byte); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + ((unsigned char *)&f)[sizeof(float) - i - 1] = + (unsigned char)(byte); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + } + + rtn_len = 64; + limit = 0; +again: + if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL) + return (NULL); + + if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) { + free(rtn); + if (limit++ > FLOAT_SPRINTF_TRY_LIMIT) + return (NULL); + rtn_len *= BUFFER_GROWFACTOR; + goto again; + } + + return rtn; +} + +static char * +decode_fp_to_float128(const char *p, size_t len) +{ + long double f; + size_t rtn_len, limit, i; + int byte; + unsigned char buf[FLOAT_QUADRUPLE_BYTES]; + char *rtn; + + switch(sizeof(long double)) { + case FLOAT_QUADRUPLE_BYTES: + return (decode_fp_to_long_double(p, len)); + case FLOAT_EXTENED_BYTES: + if (p == NULL || len == 0 || len % 2 != 0 || + len / 2 > FLOAT_QUADRUPLE_BYTES) + return (NULL); + + memset(buf, 0, FLOAT_QUADRUPLE_BYTES); + + for (i = 0; i < len / 2; ++i) { + byte = hex_to_dec(p[len - i * 2 - 1]) + + hex_to_dec(p[len - i * 2 - 2]) * 16; + if (byte < 0 || byte > 255) + return (NULL); +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + buf[i] = (unsigned char)(byte); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + buf[FLOAT_QUADRUPLE_BYTES - i -1] = + (unsigned char)(byte); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + } + memset(&f, 0, FLOAT_EXTENED_BYTES); + +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + memcpy(&f, buf, FLOAT_EXTENED_BYTES); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + + rtn_len = 256; + limit = 0; +again: + if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL) + return (NULL); + + if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) { + free(rtn); + if (limit++ > FLOAT_SPRINTF_TRY_LIMIT) + return (NULL); + rtn_len *= BUFFER_GROWFACTOR; + goto again; + } + + return (rtn); + default: + return (NULL); + } +} + +static char * +decode_fp_to_float80(const char *p, size_t len) +{ + long double f; + size_t rtn_len, limit, i; + int byte; + unsigned char buf[FLOAT_EXTENED_BYTES]; + char *rtn; + + switch(sizeof(long double)) { + case FLOAT_QUADRUPLE_BYTES: + if (p == NULL || len == 0 || len % 2 != 0 || + len / 2 > FLOAT_EXTENED_BYTES) + return (NULL); + + memset(buf, 0, FLOAT_EXTENED_BYTES); + + for (i = 0; i < len / 2; ++i) { + byte = hex_to_dec(p[len - i * 2 - 1]) + + hex_to_dec(p[len - i * 2 - 2]) * 16; + + if (byte < 0 || byte > 255) + return (NULL); + +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + buf[i] = (unsigned char)(byte); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + buf[FLOAT_EXTENED_BYTES - i -1] = + (unsigned char)(byte); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + } + + memset(&f, 0, FLOAT_QUADRUPLE_BYTES); + +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + memcpy(&f, buf, FLOAT_EXTENED_BYTES); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + + rtn_len = 256; + limit = 0; +again: + if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL) + return (NULL); + + if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) { + free(rtn); + if (limit++ > FLOAT_SPRINTF_TRY_LIMIT) + return (NULL); + rtn_len *= BUFFER_GROWFACTOR; + goto again; + } + + return (rtn); + case FLOAT_EXTENED_BYTES: + return (decode_fp_to_long_double(p, len)); + default: + return (NULL); + } +} + +static char * +decode_fp_to_long_double(const char *p, size_t len) +{ + long double f; + size_t rtn_len, limit, i; + int byte; + char *rtn; + + if (p == NULL || len == 0 || len % 2 != 0 || + len / 2 > sizeof(long double)) + return (NULL); + + memset(&f, 0, sizeof(long double)); + + for (i = 0; i < len / 2; ++i) { + byte = hex_to_dec(p[len - i * 2 - 1]) + + hex_to_dec(p[len - i * 2 - 2]) * 16; + + if (byte < 0 || byte > 255) + return (NULL); + +#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN + ((unsigned char *)&f)[i] = (unsigned char)(byte); +#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + ((unsigned char *)&f)[sizeof(long double) - i - 1] = + (unsigned char)(byte); +#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */ + } + + rtn_len = 256; + limit = 0; +again: + if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL) + return (NULL); + + if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) { + free(rtn); + if (limit++ > FLOAT_SPRINTF_TRY_LIMIT) + return (NULL); + rtn_len *= BUFFER_GROWFACTOR; + goto again; + } + + return (rtn); +} + +/* Simple hex to integer function used by decode_to_* function. */ +static int +hex_to_dec(char c) +{ + + switch (c) { + case '0': + return (0); + case '1': + return (1); + case '2': + return (2); + case '3': + return (3); + case '4': + return (4); + case '5': + return (5); + case '6': + return (6); + case '7': + return (7); + case '8': + return (8); + case '9': + return (9); + case 'a': + return (10); + case 'b': + return (11); + case 'c': + return (12); + case 'd': + return (13); + case 'e': + return (14); + case 'f': + return (15); + default: + return (-1); + }; +} + +/** + * @brief Test input string is mangled by IA-64 C++ ABI style. + * + * Test string heads with "_Z" or "_GLOBAL__I_". + * @return Return 0 at false. + */ +bool +is_cpp_mangled_gnu3(const char *org) +{ + size_t len; + + len = strlen(org); + return ((len > 2 && *org == '_' && *(org + 1) == 'Z') || + (len > 11 && !strncmp(org, "_GLOBAL__I_", 11))); +} + +static void +vector_read_cmd_dest(struct vector_read_cmd *v) +{ + + if (v == NULL) + return; + + free(v->r_container); +} + +/* return -1 at failed, 0 at not found, 1 at found. */ +static int +vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst) +{ + size_t i; + + if (v == NULL || dst == READ_FAIL) + return (-1); + + for (i = 0; i < v->size; ++i) + if (v->r_container[i] == dst) + return (1); + + return (0); +} + +static int +vector_read_cmd_init(struct vector_read_cmd *v) +{ + + if (v == NULL) + return (0); + + v->size = 0; + v->capacity = VECTOR_DEF_CAPACITY; + + if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity)) + == NULL) + return (0); + + return (1); +} + +static int +vector_read_cmd_pop(struct vector_read_cmd *v) +{ + + if (v == NULL || v->size == 0) + return (0); + + --v->size; + v->r_container[v->size] = READ_FAIL; + + return (1); +} + +static int +vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd) +{ + enum read_cmd *tmp_r_ctn; + size_t tmp_cap; + size_t i; + + if (v == NULL) + return (0); + + if (v->size == v->capacity) { + tmp_cap = v->capacity * BUFFER_GROWFACTOR; + if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap)) + == NULL) + return (0); + for (i = 0; i < v->size; ++i) + tmp_r_ctn[i] = v->r_container[i]; + free(v->r_container); + v->r_container = tmp_r_ctn; + v->capacity = tmp_cap; + } + + v->r_container[v->size] = cmd; + ++v->size; + + return (1); +} + +static void +vector_type_qualifier_dest(struct vector_type_qualifier *v) +{ + + if (v == NULL) + return; + + free(v->q_container); + vector_str_dest(&v->ext_name); +} + +/* size, capacity, ext_name */ +static int +vector_type_qualifier_init(struct vector_type_qualifier *v) +{ + + if (v == NULL) + return (0); + + v->size = 0; + v->capacity = VECTOR_DEF_CAPACITY; + + if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity)) + == NULL) + return (0); + + assert(v->q_container != NULL); + + if (vector_str_init(&v->ext_name) == false) { + free(v->q_container); + return (0); + } + + return (1); +} + +static int +vector_type_qualifier_push(struct vector_type_qualifier *v, + enum type_qualifier t) +{ + enum type_qualifier *tmp_ctn; + size_t tmp_cap; + size_t i; + + if (v == NULL) + return (0); + + if (v->size == v->capacity) { + tmp_cap = v->capacity * BUFFER_GROWFACTOR; + if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap)) + == NULL) + return (0); + for (i = 0; i < v->size; ++i) + tmp_ctn[i] = v->q_container[i]; + free(v->q_container); + v->q_container = tmp_ctn; + v->capacity = tmp_cap; + } + + v->q_container[v->size] = t; + ++v->size; + + return (1); +} diff --git a/contrib/elftoolchain/libelftc/libelftc_hash.c b/contrib/elftoolchain/libelftc/libelftc_hash.c new file mode 100644 index 000000000000..6cc54b964e46 --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_hash.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2013, Joseph Koshy + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * An implementation of the Fowler-Noll-Vo hash function. + * + * References: + * - http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function + * - http://www.isthe.com/chongo/tech/comp/fnv/ + */ + +#include + +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_hash.c 2870 2013-01-07 10:38:43Z jkoshy $"); + +/* + * Use the size of an 'int' to determine the magic numbers used by the + * hash function. + */ + +#if INT_MAX == 2147483647UL +#define FNV_PRIME 16777619UL +#define FNV_OFFSET 2166136261UL +#elif INT_MAX == 18446744073709551615ULL +#define FNV_PRIME 1099511628211ULL +#define FNV_OFFSET 14695981039346656037ULL +#else +#error sizeof(int) is unknown. +#endif + +unsigned int +libelftc_hash_string(const char *s) +{ + char c; + unsigned int hash; + + for (hash = FNV_OFFSET; (c = *s) != '\0'; s++) { + hash ^= c; + hash *= FNV_PRIME; + } + + return (hash); +} diff --git a/contrib/elftoolchain/libelftc/libelftc_vstr.c b/contrib/elftoolchain/libelftc/libelftc_vstr.c new file mode 100644 index 000000000000..4b0977efa0f5 --- /dev/null +++ b/contrib/elftoolchain/libelftc/libelftc_vstr.c @@ -0,0 +1,318 @@ +/*- + * Copyright (c) 2008 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "_libelftc.h" + +ELFTC_VCSID("$Id: libelftc_vstr.c 2065 2011-10-26 15:24:47Z jkoshy $"); + +/** + * @file vector_str.c + * @brief Dynamic vector data for string implementation. + * + * Resemble to std::vector in C++. + */ + +static size_t get_strlen_sum(const struct vector_str *v); +static bool vector_str_grow(struct vector_str *v); + +static size_t +get_strlen_sum(const struct vector_str *v) +{ + size_t i, len = 0; + + if (v == NULL) + return (0); + + assert(v->size > 0); + + for (i = 0; i < v->size; ++i) + len += strlen(v->container[i]); + + return (len); +} + +/** + * @brief Deallocate resource in vector_str. + */ +void +vector_str_dest(struct vector_str *v) +{ + size_t i; + + if (v == NULL) + return; + + for (i = 0; i < v->size; ++i) + free(v->container[i]); + + free(v->container); +} + +/** + * @brief Find string in vector_str. + * @param v Destination vector. + * @param o String to find. + * @param l Length of the string. + * @return -1 at failed, 0 at not found, 1 at found. + */ +int +vector_str_find(const struct vector_str *v, const char *o, size_t l) +{ + size_t i; + + if (v == NULL || o == NULL) + return (-1); + + for (i = 0; i < v->size; ++i) + if (strncmp(v->container[i], o, l) == 0) + return (1); + + return (0); +} + +/** + * @brief Get new allocated flat string from vector. + * + * If l is not NULL, return length of the string. + * @param v Destination vector. + * @param l Length of the string. + * @return NULL at failed or NUL terminated new allocated string. + */ +char * +vector_str_get_flat(const struct vector_str *v, size_t *l) +{ + ssize_t elem_pos, elem_size, rtn_size; + size_t i; + char *rtn; + + if (v == NULL || v->size == 0) + return (NULL); + + if ((rtn_size = get_strlen_sum(v)) == 0) + return (NULL); + + if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL) + return (NULL); + + elem_pos = 0; + for (i = 0; i < v->size; ++i) { + elem_size = strlen(v->container[i]); + + memcpy(rtn + elem_pos, v->container[i], elem_size); + + elem_pos += elem_size; + } + + rtn[rtn_size] = '\0'; + + if (l != NULL) + *l = rtn_size; + + return (rtn); +} + +static bool +vector_str_grow(struct vector_str *v) +{ + size_t i, tmp_cap; + char **tmp_ctn; + + if (v == NULL) + return (false); + + assert(v->capacity > 0); + + tmp_cap = v->capacity * BUFFER_GROWFACTOR; + + assert(tmp_cap > v->capacity); + + if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) + return (false); + + for (i = 0; i < v->size; ++i) + tmp_ctn[i] = v->container[i]; + + free(v->container); + + v->container = tmp_ctn; + v->capacity = tmp_cap; + + return (true); +} + +/** + * @brief Initialize vector_str. + * @return false at failed, true at success. + */ +bool +vector_str_init(struct vector_str *v) +{ + + if (v == NULL) + return (false); + + v->size = 0; + v->capacity = VECTOR_DEF_CAPACITY; + + assert(v->capacity > 0); + + if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL) + return (false); + + assert(v->container != NULL); + + return (true); +} + +/** + * @brief Remove last element in vector_str. + * @return false at failed, true at success. + */ +bool +vector_str_pop(struct vector_str *v) +{ + + if (v == NULL) + return (false); + + if (v->size == 0) + return (true); + + --v->size; + + free(v->container[v->size]); + v->container[v->size] = NULL; + + return (true); +} + +/** + * @brief Push back string to vector. + * @return false at failed, true at success. + */ +bool +vector_str_push(struct vector_str *v, const char *str, size_t len) +{ + + if (v == NULL || str == NULL) + return (false); + + if (v->size == v->capacity && vector_str_grow(v) == false) + return (false); + + if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL) + return (false); + + snprintf(v->container[v->size], len + 1, "%s", str); + + ++v->size; + + return (true); +} + +/** + * @brief Push front org vector to det vector. + * @return false at failed, true at success. + */ +bool +vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org) +{ + size_t i, j, tmp_cap; + char **tmp_ctn; + + if (dst == NULL || org == NULL) + return (false); + + tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR; + + if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) + return (false); + + for (i = 0; i < org->size; ++i) + if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) { + for (j = 0; j < i; ++j) + free(tmp_ctn[j]); + + free(tmp_ctn); + + return (false); + } + + for (i = 0; i < dst->size; ++i) + tmp_ctn[i + org->size] = dst->container[i]; + + free(dst->container); + + dst->container = tmp_ctn; + dst->capacity = tmp_cap; + dst->size += org->size; + + return (true); +} + +/** + * @brief Get new allocated flat string from vector between begin and end. + * + * If r_len is not NULL, string length will be returned. + * @return NULL at failed or NUL terminated new allocated string. + */ +char * +vector_str_substr(const struct vector_str *v, size_t begin, size_t end, + size_t *r_len) +{ + size_t cur, i, len; + char *rtn; + + if (v == NULL || begin > end) + return (NULL); + + len = 0; + for (i = begin; i < end + 1; ++i) + len += strlen(v->container[i]); + + if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL) + return (NULL); + + if (r_len != NULL) + *r_len = len; + + cur = 0; + for (i = begin; i < end + 1; ++i) { + len = strlen(v->container[i]); + memcpy(rtn + cur, v->container[i], len); + cur += len; + } + rtn[cur] = '\0'; + + return (rtn); +} diff --git a/contrib/elftoolchain/libelftc/make-toolchain-version b/contrib/elftoolchain/libelftc/make-toolchain-version new file mode 100755 index 000000000000..ac6155a49a00 --- /dev/null +++ b/contrib/elftoolchain/libelftc/make-toolchain-version @@ -0,0 +1,104 @@ +#!/bin/sh +# +# This script generates a project-wide version identifier for use by +# the `elftc_version()' API. +# +# $Id: make-toolchain-version 2583 2012-09-14 09:49:25Z jkoshy $ + +# +# Defaults. +# +buildhost=`uname -s` +elftcname="elftoolchain" +options="e:h:o:r:t:" +top="" +version="HEAD" +versionfile="elftc_version.c" +progname=`basename ${0}` + +usage() +{ + exec >&2 + + # Print a message, if supplied. + if [ -n "${*}" ]; then echo "##${@}"; fi + + echo "Usage: ${progname} [options]" + echo " Generate a toolchain-wide version number" + echo " -e PROJECTNAME Set the project name [default: ${elftcname}]." + echo " -h HOSTOS Set the build OS [default: ${buildhost}]." + echo " -o OUTPUT Set the output file [default: ${versionfile}]." + echo " -r VERSION Set the version string [default: ${version}]." + echo " -t TOPDIR Set the top-of-tree directory [required]." + exit 1 +} + +# +# Parse options. +# + +while getopts ${options} option +do + case ${option} in + 'e') elftcname="${OPTARG}" ;; + 'h') buildhost="${OPTARG}" ;; + 'o') versionfile="${OPTARG}" ;; + 'r') version="${OPTARG}" ;; + 't') top="${OPTARG}" ;; + '?') usage ;; + esac +done + +[ -n "${top}" ] || usage + +# Try to determine the in-tree revision number. +# +# This script attempts to handle the case where our sources have been +# incorporated into an operating system's base sources. +# +# - If SVN is detected, we use the `svninfo' tool to determine the +# in-tree revision number. +# - If CVS is detected, we use the string `unknown'. +# - Otherwise, we use `git --describe'. + +curdir=`pwd` +cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"." + +if [ -d .svn ]; then # FreeBSD and SF.Net sources. + versionstring=" svn:"$(svnversion) +elif [ -d CVS ]; then # NetBSD. + versionstring=" cvs:unknown" +else # DragonFlyBSD. + versionstring=" git:"$(git describe --all --dirty --long 2> /dev/null) + + # Cannot determine an in-tree version number. + if [ $? -ne 0 ]; then + versionstring="" + fi +fi + +cd ${curdir} || usage "Cannot change back to ${curdir}." + +# +# Only replace the source file if its content has changed. +# +tmpfile=`mktemp ${TMPDIR:-/tmp}/MV.XXXXXXX` +trap "rm -f ${tmpfile};" 0 1 2 3 15 + +cat > ${tmpfile} < +#include + +const char * +elftc_version(void) +{ + return "${elftcname} ${version} ${buildhost}${versionstring}"; +} +EOF + +if ! cmp -s ${tmpfile} ${versionfile}; then + echo "@ ${progname}: building \"${versionfile}\"." + cp ${tmpfile} ${versionfile} || exit ${?} +fi diff --git a/contrib/elftoolchain/libelftc/os.FreeBSD.mk b/contrib/elftoolchain/libelftc/os.FreeBSD.mk new file mode 100644 index 000000000000..8079a5b4f2c6 --- /dev/null +++ b/contrib/elftoolchain/libelftc/os.FreeBSD.mk @@ -0,0 +1,7 @@ +# +# Building for a FreeBSD target. +# +# $Id: os.freebsd.mk 189 2008-07-20 10:38:08Z jkoshy $ + +# Symbol versioning support [FreeBSD 7.X and later] +VERSION_MAP= ${.CURDIR}/Version.map diff --git a/contrib/elftoolchain/libelftc/os.Linux.mk b/contrib/elftoolchain/libelftc/os.Linux.mk new file mode 100644 index 000000000000..9730bf6a2788 --- /dev/null +++ b/contrib/elftoolchain/libelftc/os.Linux.mk @@ -0,0 +1,3 @@ +# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $ + +CFLAGS+= -Wall diff --git a/contrib/elftoolchain/nm/Makefile b/contrib/elftoolchain/nm/Makefile new file mode 100644 index 000000000000..6177c61221eb --- /dev/null +++ b/contrib/elftoolchain/nm/Makefile @@ -0,0 +1,13 @@ + +# $Id: Makefile 2076 2011-10-27 03:50:33Z jkoshy $ + +TOP= .. + +PROG= nm +SRCS= nm.c + +WARNS?= 6 + +LDADD= -ldwarf -lelftc -lelf + +.include "${TOP}/mk/elftoolchain.prog.mk" diff --git a/contrib/elftoolchain/nm/nm.1 b/contrib/elftoolchain/nm/nm.1 new file mode 100644 index 000000000000..0ae9a22a6afa --- /dev/null +++ b/contrib/elftoolchain/nm/nm.1 @@ -0,0 +1,334 @@ +.\" Copyright (c) 2007 Hyogeol Lee +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer +.\" in this position and unchanged. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: nm.1 2377 2012-01-03 07:10:59Z jkoshy $ +.\" +.Dd January 3, 2012 +.Os +.Dt NM 1 +.Sh NAME +.Nm nm +.Nd display symbolic information in object files +.Sh SYNOPSIS +.Nm +.Op Fl -debug-syms +.Op Fl -defined-only +.Op Fl -demangle Ns Op = Ns style +.Op Fl -dynamic +.Op Fl -help +.Op Fl -line-numbers +.Op Fl -no-demangle +.Op Fl -no-sort +.Op Fl -numeric-sort +.Op Fl -print-armap +.Op Fl -print-file-name +.Op Fl -print-size +.Op Fl -radix= Ns Ar format +.Op Fl -reverse-sort +.Op Fl -size-sort +.Op Fl -undefined-only +.Op Fl -version +.Op Fl A +.Op Fl B +.Op Fl C Op Ar style +.Op Fl D +.Op Fl P +.Op Fl V +.Op Fl a +.Op Fl e +.Op Fl g +.Op Fl h +.Op Fl l +.Op Fl n +.Op Fl o +.Op Fl p +.Op Fl r +.Op Fl S +.Op Fl s +.Op Fl t Ar format +.Op Fl u +.Op Fl x +.Ar +.Sh DESCRIPTION +The +.Nm +utility displays symbolic information in the object files, +executables, and object library files named by its arguments. +Lack of symbolic information in an otherwise valid input +file, is not considered to be an error. +If no files are specified on the command line, +.Nm +will attempt to read +.Pa a.out . +.Pp +The +.Nm +utility recognizes the following options: +.Bl -tag -width ".Fl d Ar argument" +.It Fl -debug-syms +Display all symbols, including debugger-only symbols. +.It Fl -defined-only +Display only defined symbols. +.It Fl -demangle Ns Op = Ns Ar style +Decode (demangle) low-level symbol names into human-readable names. +Supported values for argument +.Ar style +are +.Sq auto , +.Sq gnu-v2 , +.Sq gnu-v3 +and +.Sq arm. +If argument +.Ar style +is not specified, it is taken to be +.Sq auto . +.It Fl -dynamic +Only display dynamic symbols. +This option is only meaningful for shared libraries. +.It Fl -help +Display a help message and exit. +.It Fl -format Ns = Ns Ar format +Display output in the format specified by argument +.Ar format . +Supported values for the format argument are +.Sq bsd , +.Sq sysv , +and +.Sq posix . +The default output format is +.Sq bsd . +.It Fl -line-numbers +Display the filename and line number associated a symbol using +any debugging information present in the input file. +For defined symbols, look up the line number associated with +the address of the symbol. +For undefined symbols, look up the line number associated with +a relocation entry that refers to the symbol. +If line number information can be determined, it is displayed after +other symbol information. +.It Fl -no-demangle +Do not demangle symbol names (default). +.It Fl -no-sort +Do not sort symbols. +.It Fl -numeric-sort +Sort symbols numerically by address instead of alphabetically by name. +.It Fl -print-armap +For +.Xr ar 1 +archives, include the index of the archive's members. +.It Fl -print-file-name +Write the full pathname or library name of an object on each line, +before the rest of the information for a symbol. +If this option is not specified, +.Nm +will only identify an input file once, before its symbols are +listed. +.It Fl -print-size +Print the size of each symbol instead of its value. +.It Fl -radix Ns = Ns Ar radix +Print numeric values using the specified radix. +Supported values for argument +.Ar radix +are +.Sq d +for decimal, +.Sq o +for octal, and +.Sq x +for hexadecimal. +.It Fl -reverse-sort +Reverse the order of the sort. +.It Fl -size-sort +Sort symbols by size instead of alphabetically by name. +.It Fl -undefined-only +Display only undefined symbols. +.It Fl -version +Display the version identifier for +.Nm +and exit. +.It Fl A +Equivalent to specifying option +.Fl -print-file-name . +.It Fl B +Equivalent to specifying option +.Fl -format= Ns Ar bsd . +.It Fl C Op Ar style +Equivalent to specifying option +.Fl -demangle Ns Op = Ns Ar style . +.It Fl D +Equivalent to specifying option +.Fl -dynamic . +.It Fl F Ar format +Equivalent to specifying option +.Fl -format Ns = Ns Ar format . +.It Fl P +Equivalent to specifying option +.Fl -format Ns = Ns Ar posix . +.It Fl S +Equivalent to specifying option +.Fl -print-size . +.It Fl V +Equivalent to specifying option +.Fl -version . +.It Fl a +Equivalent to specifying option +.Fl -debug-syms . +.It Fl e +Only display information for global and static symbols. +.It Fl f +Produce full output (default). +.It Fl g +Only display information about global (external) symbols. +.It Fl h +Equivalent to specifying option +.Fl -help . +.It Fl l +Equivalent to specifying option +.Fl -line-numbers . +.It Fl n +Equivalent to specifying option +.Fl -numeric-sort . +.It Fl o +If POSIX output was specified using the +.Fl F Ar posix +or +.Fl P +options, this option is equivalent to specifying +.Fl -radix Ns = Ns Sq Ar o . +If POSIX output was not specified, this option +acts as a synonym for the +.Fl -print-file-name +option. +.It Fl p +Equivalent to specifying option +.Fl -no-sort . +.It Fl v +Equivalent to option +.Fl n . +.It Fl r +Equivalent to specifying option +.Fl -reverse-sort +.It Fl s +Equivalent to specifying option +.Fl -print-armap . +.It Fl t Ar radix +Equivalent to specifying option +.Fl -radix= Ns Ar radix . +.It Fl u +Equivalent to specifying option +.Fl -undefined-only . +.It Fl x +Write numeric values in hexadecimal (equivalent to -t x). +.El +.Sh OUTPUT FORMAT +.Pp +The +.Nm +utility can present its information in a number of formats, numeric +radices and sort orders. +By default +.Nm +uses BSD style output, a hexadecimal radix, without output sorted +alphabetically by name and without demangling of names. +.Pp +For each symbol listed, +.Nm +presents the following information: +.Bl -bullet -compact +.It +The library or object name, if options +.Fl A +or +.Fl -print-file-name +were specified. +.It +The symbol name. +.It +The type of the symbol denoted by a single character as below: +.Bl -tag -compact -width indent +.It A +A global, absolute symbol. +.It B +A global +.Dq bss +(uninitialized data) symbol. +.It C +A +.Dq common +symbol, representing uninitialized data. +.It D +A global symbol naming initialized data. +.It N +A debugger symbol. +.It R +A read-only data symbol. +.It T +A global text symbol. +.It U +An undefined symbol. +.It V +A weak object. +.It W +A weak reference. +.It a +A local absolute symbol. +.It b +A local +.Dq bss +(uninitialized data) symbol. +.It d +A local data symbol. +.It t +A local text symbol. +.It v +A weak object that is undefined. +.It w +A weak symbol that is undefined. +.It ? +None of the above. +.El +.It +The value of the symbol. +.It +The size of the symbol if applicable. +.It +Line number information, if available and if options +.Fl l +or +.Fl -line-numbers +were specified. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr ar 1 , +.Xr objdump 1 , +.Xr ranlib 1 , +.Xr elf 3 +.Sh AUTHORS +The +.Nm +utility and this manual page were written by +.An Hyogeol Lee Aq hyogeollee@gmail.com . diff --git a/contrib/elftoolchain/nm/nm.c b/contrib/elftoolchain/nm/nm.c new file mode 100644 index 000000000000..6c10e0dbf586 --- /dev/null +++ b/contrib/elftoolchain/nm/nm.c @@ -0,0 +1,2096 @@ +/*- + * Copyright (c) 2007 Hyogeol Lee + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: nm.c 2484 2012-04-07 15:52:05Z kaiwang27 $"); + +/* symbol information list */ +STAILQ_HEAD(sym_head, sym_entry); + +struct sym_entry { + char *name; + GElf_Sym *sym; + STAILQ_ENTRY(sym_entry) sym_entries; +}; + +typedef int (*fn_sort)(const void *, const void *); +typedef void (*fn_elem_print)(char, const char *, const GElf_Sym *, const char *); +typedef void (*fn_sym_print)(const GElf_Sym *); +typedef int (*fn_filter)(char, const GElf_Sym *, const char *); + +/* output filter list */ +SLIST_HEAD(filter_head, filter_entry) nm_out_filter = + SLIST_HEAD_INITIALIZER(nm_out_filter); + +struct filter_entry { + fn_filter fn; + SLIST_ENTRY(filter_entry) filter_entries; +}; + +struct sym_print_data { + struct sym_head *headp; + size_t sh_num, list_num; + const char *t_table, **s_table, *filename, *objname; +}; + +struct nm_prog_info { + const char *name; + const char *def_filename; +}; + +/* List for line number information. */ +struct line_info_entry { + uint64_t addr; /* address */ + uint64_t line; /* line number */ + char *file; /* file name with path */ + SLIST_ENTRY(line_info_entry) entries; +}; +SLIST_HEAD(line_info_head, line_info_entry); + +/* List for function line number information. */ +struct func_info_entry { + char *name; /* function name */ + char *file; /* file name with path */ + uint64_t lowpc; /* low address */ + uint64_t highpc; /* high address */ + uint64_t line; /* line number */ + SLIST_ENTRY(func_info_entry) entries; +}; +SLIST_HEAD(func_info_head, func_info_entry); + +/* List for variable line number information. */ +struct var_info_entry { + char *name; /* variable name */ + char *file; /* file name with path */ + uint64_t addr; /* address */ + uint64_t line; /* line number */ + SLIST_ENTRY(var_info_entry) entries; +}; +SLIST_HEAD(var_info_head, var_info_entry); + +/* output numric type */ +enum radix { + RADIX_OCT, + RADIX_HEX, + RADIX_DEC +}; + +/* output symbol type, PRINT_SYM_DYN for dynamic symbol only */ +enum print_symbol { + PRINT_SYM_SYM, + PRINT_SYM_DYN +}; + +/* output name type */ +enum print_name { + PRINT_NAME_NONE, + PRINT_NAME_FULL, + PRINT_NAME_MULTI +}; + +struct nm_prog_options { + enum print_symbol print_symbol; + enum print_name print_name; + enum radix t; + int demangle_type; + bool print_debug; + bool print_armap; + int print_size; + bool debug_line; + int def_only; + bool undef_only; + int sort_size; + bool sort_reverse; + int no_demangle; + + /* + * function pointer to sort symbol list. + * possible function - cmp_name, cmp_none, cmp_size, cmp_value + */ + fn_sort sort_fn; + + /* + * function pointer to print symbol elem. + * possible function - sym_elem_print_all + * sym_elem_print_all_portable + * sym_elem_print_all_sysv + */ + fn_elem_print elem_print_fn; + + fn_sym_print value_print_fn; + fn_sym_print size_print_fn; +}; + +#define CHECK_SYM_PRINT_DATA(p) (p->headp == NULL || p->sh_num == 0 || \ +p->t_table == NULL || p->s_table == NULL || p->filename == NULL) +#define IS_SYM_TYPE(t) ((t) == '?' || isalpha((t)) != 0) +#define IS_UNDEF_SYM_TYPE(t) ((t) == 'U' || (t) == 'v' || (t) == 'w') +#define UNUSED(p) ((void)p) + +static int cmp_name(const void *, const void *); +static int cmp_none(const void *, const void *); +static int cmp_size(const void *, const void *); +static int cmp_value(const void *, const void *); +static void filter_dest(void); +static int filter_insert(fn_filter); +static void get_opt(int, char **); +static int get_sym(Elf *, struct sym_head *, int, size_t, size_t, + const char *, const char **, int); +static const char * get_sym_name(Elf *, const GElf_Sym *, size_t, + const char **, int); +static char get_sym_type(const GElf_Sym *, const char *); +static void global_dest(void); +static void global_init(void); +static bool is_sec_data(GElf_Shdr *); +static bool is_sec_debug(const char *); +static bool is_sec_nobits(GElf_Shdr *); +static bool is_sec_readonly(GElf_Shdr *); +static bool is_sec_text(GElf_Shdr *); +static void print_ar_index(int, Elf *); +static void print_header(const char *, const char *); +static void print_version(void); +static int read_elf(Elf *, const char *, Elf_Kind); +static int read_object(const char *); +static int read_files(int, char **); +static void set_opt_value_print_fn(enum radix); +static int sym_elem_def(char, const GElf_Sym *, const char *); +static int sym_elem_global(char, const GElf_Sym *, const char *); +static int sym_elem_global_static(char, const GElf_Sym *, + const char *); +static int sym_elem_nondebug(char, const GElf_Sym *, const char *); +static int sym_elem_nonzero_size(char, const GElf_Sym *, + const char *); +static void sym_elem_print_all(char, const char *, + const GElf_Sym *, const char *); +static void sym_elem_print_all_portable(char, const char *, + const GElf_Sym *, const char *); +static void sym_elem_print_all_sysv(char, const char *, + const GElf_Sym *, const char *); +static int sym_elem_undef(char, const GElf_Sym *, const char *); +static void sym_list_dest(struct sym_head *); +static int sym_list_insert(struct sym_head *, const char *, + const GElf_Sym *); +static void sym_list_print(struct sym_print_data *, + struct func_info_head *, struct var_info_head *, + struct line_info_head *); +static void sym_list_print_each(struct sym_entry *, + struct sym_print_data *, struct func_info_head *, + struct var_info_head *, struct line_info_head *); +static struct sym_entry *sym_list_sort(struct sym_print_data *); +static void sym_size_oct_print(const GElf_Sym *); +static void sym_size_hex_print(const GElf_Sym *); +static void sym_size_dec_print(const GElf_Sym *); +static void sym_value_oct_print(const GElf_Sym *); +static void sym_value_hex_print(const GElf_Sym *); +static void sym_value_dec_print(const GElf_Sym *); +static void usage(int); + +static struct nm_prog_info nm_info; +static struct nm_prog_options nm_opts; +static int nm_elfclass; + +/* + * Point to current sym_print_data to use portable qsort function. + * (e.g. There is no qsort_r function in NetBSD.) + * + * Using in sym_list_sort. + */ +static struct sym_print_data *nm_print_data; + +static const struct option nm_longopts[] = { + { "debug-syms", no_argument, NULL, 'a' }, + { "defined-only", no_argument, &nm_opts.def_only, 1}, + { "demangle", optional_argument, NULL, 'C' }, + { "dynamic", no_argument, NULL, 'D' }, + { "format", required_argument, NULL, 'F' }, + { "help", no_argument, NULL, 'h' }, + { "line-numbers", no_argument, NULL, 'l' }, + { "no-demangle", no_argument, &nm_opts.no_demangle, + 1}, + { "no-sort", no_argument, NULL, 'p' }, + { "numeric-sort", no_argument, NULL, 'v' }, + { "print-armap", no_argument, NULL, 's' }, + { "print-file-name", no_argument, NULL, 'A' }, + { "print-size", no_argument, NULL, 'S' }, + { "radix", required_argument, NULL, 't' }, + { "reverse-sort", no_argument, NULL, 'r' }, + { "size-sort", no_argument, &nm_opts.sort_size, 1}, + { "undefined-only", no_argument, NULL, 'u' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) +static __inline uint32_t +be32dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +static __inline uint32_t +le32dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); +} + +static __inline uint64_t +be64dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); +} + +static __inline uint64_t +le64dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); +} +#endif + +static int +cmp_name(const void *l, const void *r) +{ + + assert(l != NULL); + assert(r != NULL); + assert(((const struct sym_entry *)l)->name != NULL); + assert(((const struct sym_entry *)r)->name != NULL); + + return (strcmp(((const struct sym_entry *)l)->name, + ((const struct sym_entry *)r)->name)); +} + +static int +cmp_none(const void *l, const void *r) +{ + + UNUSED(l); + UNUSED(r); + + return (0); +} + +/* Size comparison. If l and r have same size, compare their name. */ +static int +cmp_size(const void *lp, const void *rp) +{ + const struct sym_entry *l, *r; + + l = lp; + r = rp; + + assert(l != NULL); + assert(l->name != NULL); + assert(l->sym != NULL); + assert(r != NULL); + assert(r->name != NULL); + assert(r->sym != NULL); + + if (l->sym->st_size == r->sym->st_size) + return (strcmp(l->name, r->name)); + + return (l->sym->st_size - r->sym->st_size); +} + +/* Value comparison. Undefined symbols come first. */ +static int +cmp_value(const void *lp, const void *rp) +{ + const struct sym_entry *l, *r; + const char *ttable; + int l_is_undef, r_is_undef; + + l = lp; + r = rp; + + assert(nm_print_data != NULL); + ttable = nm_print_data->t_table; + + assert(l != NULL); + assert(l->name != NULL); + assert(l->sym != NULL); + assert(r != NULL); + assert(r->name != NULL); + assert(r->sym != NULL); + assert(ttable != NULL); + + l_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(l->sym, ttable)) ? 1 : 0; + r_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(r->sym, ttable)) ? 1 : 0; + + assert(l_is_undef + r_is_undef >= 0); + assert(l_is_undef + r_is_undef <= 2); + + switch (l_is_undef + r_is_undef) { + case 0: + /* Both defined */ + if (l->sym->st_value == r->sym->st_value) + return (strcmp(l->name, r->name)); + return (l->sym->st_value - r->sym->st_value); + case 1: + /* One undefined */ + return (l_is_undef == 0 ? 1 : -1); + case 2: + /* Both undefined */ + return (strcmp(l->name, r->name)); + } + /* NOTREACHED */ + + return (l->sym->st_value - r->sym->st_value); +} + +static void +filter_dest(void) +{ + struct filter_entry *e; + + while (!SLIST_EMPTY(&nm_out_filter)) { + e = SLIST_FIRST(&nm_out_filter); + SLIST_REMOVE_HEAD(&nm_out_filter, filter_entries); + free(e); + } +} + +static int +filter_insert(fn_filter filter_fn) +{ + struct filter_entry *e; + + assert(filter_fn != NULL); + + if ((e = malloc(sizeof(struct filter_entry))) == NULL) { + warn("malloc"); + return (0); + } + e->fn = filter_fn; + SLIST_INSERT_HEAD(&nm_out_filter, e, filter_entries); + + return (1); +} + +static int +parse_demangle_option(const char *opt) +{ + + if (opt == NULL) + return (ELFTC_DEM_UNKNOWN); + else if (!strncasecmp(opt, "gnu-v2", 6)) + return (ELFTC_DEM_GNU2); + else if (!strncasecmp(opt, "gnu-v3", 6)) + return (ELFTC_DEM_GNU3); + else if (!strncasecmp(opt, "arm", 3)) + return (ELFTC_DEM_ARM); + else + errx(EXIT_FAILURE, "unknown demangling style '%s'", opt); + + /* NOTREACHED */ + return (0); +} + +static void +get_opt(int argc, char **argv) +{ + int ch; + bool is_posix, oflag; + + if (argc <= 0 || argv == NULL) + return; + + oflag = is_posix = false; + nm_opts.t = RADIX_HEX; + while ((ch = getopt_long(argc, argv, "ABCDF:PSVaefghlnoprst:uvx", + nm_longopts, NULL)) != -1) { + switch (ch) { + case 'A': + nm_opts.print_name = PRINT_NAME_FULL; + break; + case 'B': + nm_opts.elem_print_fn = &sym_elem_print_all; + break; + case 'C': + nm_opts.demangle_type = parse_demangle_option(optarg); + break; + case 'D': + nm_opts.print_symbol = PRINT_SYM_DYN; + break; + case 'F': + /* sysv, bsd, posix */ + switch (optarg[0]) { + case 'B': + case 'b': + nm_opts.elem_print_fn = &sym_elem_print_all; + break; + case 'P': + case 'p': + is_posix = true; + nm_opts.elem_print_fn = + &sym_elem_print_all_portable; + break; + case 'S': + case 's': + nm_opts.elem_print_fn = + &sym_elem_print_all_sysv; + break; + default: + warnx("%s: Invalid format", optarg); + usage(1); + } + + break; + case 'P': + is_posix = true; + nm_opts.elem_print_fn = &sym_elem_print_all_portable; + break; + case 'S': + nm_opts.print_size = 1; + break; + case 'V': + print_version(); + /* NOTREACHED */ + case 'a': + nm_opts.print_debug = true; + break; + case 'e': + filter_insert(sym_elem_global_static); + break; + case 'f': + break; + case 'g': + filter_insert(sym_elem_global); + break; + case 'h': + usage(0); + break; + case 'l': + nm_opts.debug_line = true; + break; + case 'n': + case 'v': + nm_opts.sort_fn = &cmp_value; + break; + case 'o': + oflag = true; + break; + case 'p': + nm_opts.sort_fn = &cmp_none; + break; + case 'r': + nm_opts.sort_reverse = true; + break; + case 's': + nm_opts.print_armap = true; + break; + case 't': + /* t require always argument to getopt_long */ + switch (optarg[0]) { + case 'd': + nm_opts.t = RADIX_DEC; + break; + case 'o': + nm_opts.t = RADIX_OCT; + break; + case 'x': + nm_opts.t = RADIX_HEX; + break; + default: + warnx("%s: Invalid radix", optarg); + usage(1); + } + break; + case 'u': + filter_insert(sym_elem_undef); + nm_opts.undef_only = true; + break; + /* case 'v': see case 'n' above. */ + case 'x': + nm_opts.t = RADIX_HEX; + break; + case 0: + if (nm_opts.sort_size != 0) { + nm_opts.sort_fn = &cmp_size; + filter_insert(sym_elem_def); + filter_insert(sym_elem_nonzero_size); + } + if (nm_opts.def_only != 0) + filter_insert(sym_elem_def); + if (nm_opts.no_demangle != 0) + nm_opts.demangle_type = -1; + break; + default : + usage(1); + } + } + + /* + * In POSIX mode, the '-o' option controls the output radix. + * In non-POSIX mode, the option is a synonym for the '-A' and + * '--print-file-name' options. + */ + if (oflag) { + if (is_posix) + nm_opts.t = RADIX_OCT; + else + nm_opts.print_name = PRINT_NAME_FULL; + } + + assert(nm_opts.sort_fn != NULL && "nm_opts.sort_fn is null"); + assert(nm_opts.elem_print_fn != NULL && + "nm_opts.elem_print_fn is null"); + assert(nm_opts.value_print_fn != NULL && + "nm_opts.value_print_fn is null"); + + set_opt_value_print_fn(nm_opts.t); + + if (nm_opts.undef_only == true) { + if (nm_opts.sort_fn == &cmp_size) + errx(EXIT_FAILURE, + "--size-sort with -u is meaningless"); + if (nm_opts.def_only != 0) + errx(EXIT_FAILURE, + "-u with --defined-only is meaningless"); + } + if (nm_opts.print_debug == false) + filter_insert(sym_elem_nondebug); + if (nm_opts.sort_reverse == true && nm_opts.sort_fn == cmp_none) + nm_opts.sort_reverse = false; +} + +/* + * Get symbol information from elf. + */ +static int +get_sym(Elf *elf, struct sym_head *headp, int shnum, size_t dynndx, + size_t strndx, const char *type_table, const char **sec_table, + int sec_table_size) +{ + Elf_Scn *scn; + Elf_Data *data; + GElf_Shdr shdr; + GElf_Sym sym; + struct filter_entry *fep; + size_t ndx; + int rtn; + const char *sym_name; + char type; + bool filter; + int i, j; + + assert(elf != NULL); + assert(headp != NULL); + + rtn = 0; + for (i = 1; i < shnum; i++) { + if ((scn = elf_getscn(elf, i)) == NULL) { + warnx("elf_getscn failed: %s", elf_errmsg(-1)); + continue; + } + if (gelf_getshdr(scn, &shdr) != &shdr) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + continue; + } + if (shdr.sh_type == SHT_SYMTAB) { + if (nm_opts.print_symbol != PRINT_SYM_SYM) + continue; + } else if (shdr.sh_type == SHT_DYNSYM) { + if (nm_opts.print_symbol != PRINT_SYM_DYN) + continue; + } else + continue; + + ndx = shdr.sh_type == SHT_DYNSYM ? dynndx : strndx; + + data = NULL; + while ((data = elf_getdata(scn, data)) != NULL) { + j = 1; + while (gelf_getsym(data, j++, &sym) != NULL) { + sym_name = get_sym_name(elf, &sym, ndx, + sec_table, sec_table_size); + filter = false; + type = get_sym_type(&sym, type_table); + SLIST_FOREACH(fep, &nm_out_filter, + filter_entries) { + if (!fep->fn(type, &sym, sym_name)) { + filter = true; + break; + } + } + if (filter == false) { + if (sym_list_insert(headp, sym_name, + &sym) == 0) + return (0); + rtn++; + } + } + } + } + + return (rtn); +} + +static const char * +get_sym_name(Elf *elf, const GElf_Sym *sym, size_t ndx, const char **sec_table, + int sec_table_size) +{ + const char *sym_name; + + sym_name = NULL; + + /* Show section name as symbol name for STT_SECTION symbols. */ + if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) { + if (sec_table != NULL && sym->st_shndx < sec_table_size) + sym_name = sec_table[sym->st_shndx]; + } else + sym_name = elf_strptr(elf, ndx, sym->st_name); + + if (sym_name == NULL) + sym_name = "(null)"; + + return (sym_name); +} + +static char +get_sym_type(const GElf_Sym *sym, const char *type_table) +{ + bool is_local; + + if (sym == NULL || type_table == NULL) + return ('?'); + + is_local = sym->st_info >> 4 == STB_LOCAL; + + if (sym->st_shndx == SHN_ABS) /* absolute */ + return (is_local ? 'a' : 'A'); + + if (sym->st_shndx == SHN_COMMON) /* common */ + return ('C'); + + if ((sym->st_info) >> 4 == STB_WEAK) { /* weak */ + if ((sym->st_info & 0xf) == STT_OBJECT) + return (sym->st_shndx == SHN_UNDEF ? 'v' : 'V'); + + return (sym->st_shndx == SHN_UNDEF ? 'w' : 'W'); + } + + if (sym->st_shndx == SHN_UNDEF) /* undefined */ + return ('U'); + + return (is_local == true && type_table[sym->st_shndx] != 'N' ? + tolower((unsigned char) type_table[sym->st_shndx]) : + type_table[sym->st_shndx]); +} + +static void +global_dest(void) +{ + + filter_dest(); +} + +static void +global_init(void) +{ + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "elf_version error"); + + nm_info.name = ELFTC_GETPROGNAME(); + nm_info.def_filename = "a.out"; + nm_opts.print_symbol = PRINT_SYM_SYM; + nm_opts.print_name = PRINT_NAME_NONE; + nm_opts.demangle_type = -1; + nm_opts.print_debug = false; + nm_opts.print_armap = false; + nm_opts.print_size = 0; + nm_opts.debug_line = false; + nm_opts.def_only = 0; + nm_opts.undef_only = false; + nm_opts.sort_size = 0; + nm_opts.sort_reverse = false; + nm_opts.no_demangle = 0; + nm_opts.sort_fn = &cmp_name; + nm_opts.elem_print_fn = &sym_elem_print_all; + nm_opts.value_print_fn = &sym_value_dec_print; + nm_opts.size_print_fn = &sym_size_dec_print; + SLIST_INIT(&nm_out_filter); +} + +static bool +is_sec_data(GElf_Shdr *s) +{ + + assert(s != NULL && "shdr is NULL"); + + return (((s->sh_flags & SHF_ALLOC) != 0) && s->sh_type != SHT_NOBITS); +} + +static bool +is_sec_debug(const char *shname) +{ + const char *dbg_sec[] = { + ".debug", + ".gnu.linkonce.wi.", + ".line", + ".rel.debug", + ".rela.debug", + ".stab", + NULL + }; + const char **p; + + assert(shname != NULL && "shname is NULL"); + + for (p = dbg_sec; *p; p++) { + if (!strncmp(shname, *p, strlen(*p))) + return (true); + } + + return (false); +} + +static bool +is_sec_nobits(GElf_Shdr *s) +{ + + assert(s != NULL && "shdr is NULL"); + + return (s->sh_type == SHT_NOBITS); +} + +static bool +is_sec_readonly(GElf_Shdr *s) +{ + + assert(s != NULL && "shdr is NULL"); + + return ((s->sh_flags & SHF_WRITE) == 0); +} + +static bool +is_sec_text(GElf_Shdr *s) +{ + + assert(s != NULL && "shdr is NULL"); + + return ((s->sh_flags & SHF_EXECINSTR) != 0); +} + +static void +print_ar_index(int fd, Elf *arf) +{ + Elf *elf; + Elf_Arhdr *arhdr; + Elf_Arsym *arsym; + Elf_Cmd cmd; + off_t start; + size_t arsym_size; + + if (arf == NULL) + return; + + if ((arsym = elf_getarsym(arf, &arsym_size)) == NULL) + return; + + printf("\nArchive index:\n"); + + start = arsym->as_off; + cmd = ELF_C_READ; + while (arsym_size > 1) { + if (elf_rand(arf, arsym->as_off) == arsym->as_off && + (elf = elf_begin(fd, cmd, arf)) != NULL) { + if ((arhdr = elf_getarhdr(elf)) != NULL) + printf("%s in %s\n", arsym->as_name, + arhdr->ar_name != NULL ? + arhdr->ar_name : arhdr->ar_rawname); + elf_end(elf); + } + ++arsym; + --arsym_size; + } + + elf_rand(arf, start); +} + +#define DEMANGLED_BUFFER_SIZE (8 * 1024) +#define PRINT_DEMANGLED_NAME(FORMAT, NAME) do { \ + char _demangled[DEMANGLED_BUFFER_SIZE]; \ + if (nm_opts.demangle_type < 0 || \ + elftc_demangle((NAME), _demangled, sizeof(_demangled), \ + nm_opts.demangle_type) < 0) \ + printf((FORMAT), (NAME)); \ + else \ + printf((FORMAT), _demangled); \ + } while (0) + +static void +print_header(const char *file, const char *obj) +{ + + if (file == NULL) + return; + + if (nm_opts.elem_print_fn == &sym_elem_print_all_sysv) { + printf("\n\n%s from %s", + nm_opts.undef_only == false ? "Symbols" : + "Undefined symbols", file); + if (obj != NULL) + printf("[%s]", obj); + printf(":\n\n"); + + printf("\ +Name Value Class Type Size Line Section\n\n"); + } else { + /* archive file without -A option and POSIX */ + if (nm_opts.print_name != PRINT_NAME_FULL && obj != NULL) { + if (nm_opts.elem_print_fn == + sym_elem_print_all_portable) + printf("%s[%s]:\n", file, obj); + else if (nm_opts.elem_print_fn == sym_elem_print_all) + printf("\n%s:\n", obj); + /* multiple files(not archive) without -A option */ + } else if (nm_opts.print_name == PRINT_NAME_MULTI) { + if (nm_opts.elem_print_fn == sym_elem_print_all) + printf("\n"); + printf("%s:\n", file); + } + } +} + +static void +print_version(void) +{ + + (void) printf("%s (%s)\n", nm_info.name, elftc_version()); + exit(0); +} + +static uint64_t +get_block_value(Dwarf_Debug dbg, Dwarf_Block *block) +{ + Elf *elf; + GElf_Ehdr eh; + Dwarf_Error de; + + if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK) { + warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de)); + return (0); + } + + if (gelf_getehdr(elf, &eh) != &eh) { + warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); + return (0); + } + + if (block->bl_len == 5) { + if (eh.e_ident[EI_DATA] == ELFDATA2LSB) + return (le32dec((uint8_t *) block->bl_data + 1)); + else + return (be32dec((uint8_t *) block->bl_data + 1)); + } else if (block->bl_len == 9) { + if (eh.e_ident[EI_DATA] == ELFDATA2LSB) + return (le64dec((uint8_t *) block->bl_data + 1)); + else + return (be64dec((uint8_t *) block->bl_data + 1)); + } + + return (0); +} + +static void +search_line_attr(Dwarf_Debug dbg, struct func_info_head *func_info, + struct var_info_head *var_info, Dwarf_Die die, char **src_files, + Dwarf_Signed filecount) +{ + Dwarf_Attribute at; + Dwarf_Unsigned udata; + Dwarf_Half tag; + Dwarf_Block *block; + Dwarf_Bool flag; + Dwarf_Die ret_die; + Dwarf_Error de; + struct func_info_entry *func; + struct var_info_entry *var; + const char *str; + int ret; + + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + + /* We're interested in DIEs which define functions or variables. */ + if (tag != DW_TAG_subprogram && tag != DW_TAG_entry_point && + tag != DW_TAG_inlined_subroutine && tag != DW_TAG_variable) + goto cont_search; + + if (tag == DW_TAG_variable) { + + /* Ignore "artificial" variable. */ + if (dwarf_attrval_flag(die, DW_AT_artificial, &flag, &de) == + DW_DLV_OK && flag) + goto cont_search; + + /* Ignore pure declaration. */ + if (dwarf_attrval_flag(die, DW_AT_declaration, &flag, &de) == + DW_DLV_OK && flag) + goto cont_search; + + /* Ignore stack varaibles. */ + if (dwarf_attrval_flag(die, DW_AT_external, &flag, &de) != + DW_DLV_OK || !flag) + goto cont_search; + + if ((var = calloc(1, sizeof(*var))) == NULL) { + warn("calloc failed"); + goto cont_search; + } + + if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata, + &de) == DW_DLV_OK && udata > 0 && + (Dwarf_Signed) (udata - 1) < filecount) { + var->file = strdup(src_files[udata - 1]); + if (var->file == NULL) { + warn("strdup"); + free(var); + goto cont_search; + } + } + + if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) == + DW_DLV_OK) + var->line = udata; + + if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == + DW_DLV_OK) { + var->name = strdup(str); + if (var->name == NULL) { + warn("strdup"); + if (var->file) + free(var->file); + free(var); + goto cont_search; + } + } + + if (dwarf_attr(die, DW_AT_location, &at, &de) == DW_DLV_OK && + dwarf_formblock(at, &block, &de) == DW_DLV_OK) { + /* + * Since we ignored stack variables, the rest are the + * external varaibles which should always use DW_OP_addr + * operator for DW_AT_location value. + */ + if (*((uint8_t *)block->bl_data) == DW_OP_addr) + var->addr = get_block_value(dbg, block); + } + + SLIST_INSERT_HEAD(var_info, var, entries); + + } else { + + if ((func = calloc(1, sizeof(*func))) == NULL) { + warn("calloc failed"); + goto cont_search; + } + + /* + * Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin + * internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line + * attributes for inlined functions as well. + */ + if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata, + &de) == DW_DLV_OK && udata > 0 && + (Dwarf_Signed) (udata - 1) < filecount) { + func->file = strdup(src_files[udata - 1]); + if (func->file == NULL) { + warn("strdup"); + free(func); + goto cont_search; + } + } + + if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) == + DW_DLV_OK) + func->line = udata; + + if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == + DW_DLV_OK) { + func->name = strdup(str); + if (func->name == NULL) { + warn("strdup"); + if (func->file) + free(func->file); + free(func); + goto cont_search; + } + } + + if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &udata, &de) == + DW_DLV_OK) + func->lowpc = udata; + if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &udata, &de) == + DW_DLV_OK) + func->highpc = udata; + + SLIST_INSERT_HEAD(func_info, func, entries); + } + +cont_search: + + /* Search children. */ + ret = dwarf_child(die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_child: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_line_attr(dbg, func_info, var_info, ret_die, src_files, + filecount); + + /* Search sibling. */ + ret = dwarf_siblingof(dbg, die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_line_attr(dbg, func_info, var_info, ret_die, src_files, + filecount); + + dwarf_dealloc(dbg, die, DW_DLA_DIE); +} + +/* + * Read elf file and collect symbol information, sort them, print. + * Return 1 at failed, 0 at success. + */ +static int +read_elf(Elf *elf, const char *filename, Elf_Kind kind) +{ + Dwarf_Debug dbg; + Dwarf_Die die; + Dwarf_Error de; + Dwarf_Half tag; + Elf_Arhdr *arhdr; + Elf_Scn *scn; + GElf_Shdr shdr; + GElf_Half i; + Dwarf_Line *lbuf; + Dwarf_Unsigned lineno; + Dwarf_Signed lcount, filecount; + Dwarf_Addr lineaddr; + struct sym_print_data p_data; + struct sym_head list_head; + struct line_info_head *line_info; + struct func_info_head *func_info; + struct var_info_head *var_info; + struct line_info_entry *lie; + struct func_info_entry *func; + struct var_info_entry *var; + const char *shname, *objname; + char *type_table, **sec_table, *sfile, **src_files; + size_t shstrndx, shnum, dynndx, strndx; + int ret, rtn, e_err; + +#define OBJNAME (objname == NULL ? filename : objname) + + assert(filename != NULL && "filename is null"); + + STAILQ_INIT(&list_head); + type_table = NULL; + sec_table = NULL; + line_info = NULL; + func_info = NULL; + var_info = NULL; + objname = NULL; + dynndx = SHN_UNDEF; + strndx = SHN_UNDEF; + rtn = 0; + + nm_elfclass = gelf_getclass(elf); + + if (kind == ELF_K_AR) { + if ((arhdr = elf_getarhdr(elf)) == NULL) + goto next_cmd; + objname = arhdr->ar_name != NULL ? arhdr->ar_name : + arhdr->ar_rawname; + } + if (!elf_getshnum(elf, &shnum)) { + if ((e_err = elf_errno()) != 0) + warnx("%s: %s", OBJNAME, elf_errmsg(e_err)); + else + warnx("%s: cannot get section number", OBJNAME); + rtn = 1; + goto next_cmd; + } + if (shnum == 0) { + warnx("%s: has no section", OBJNAME); + rtn = 1; + goto next_cmd; + } + if (!elf_getshstrndx(elf, &shstrndx)) { + warnx("%s: cannot get str index", OBJNAME); + rtn = 1; + goto next_cmd; + } + /* type_table for type determine */ + if ((type_table = malloc(sizeof(char) * shnum)) == NULL) { + warn("%s: malloc", OBJNAME); + rtn = 1; + goto next_cmd; + } + /* sec_table for section name to display in sysv format */ + if ((sec_table = calloc(shnum, sizeof(char *))) == NULL) { + warn("%s: calloc", OBJNAME); + rtn = 1; + goto next_cmd; + } + + type_table[0] = 'U'; + if ((sec_table[0] = strdup("*UND*")) == NULL) { + warn("strdup"); + goto next_cmd; + } + + for (i = 1; i < shnum; ++i) { + type_table[i] = 'U'; + if ((scn = elf_getscn(elf, i)) == NULL) { + if ((e_err = elf_errno()) != 0) + warnx("%s: %s", OBJNAME, elf_errmsg(e_err)); + else + warnx("%s: cannot get section", OBJNAME); + rtn = 1; + goto next_cmd; + } + if (gelf_getshdr(scn, &shdr) == NULL) + goto next_cmd; + + /* + * Cannot test by type and attribute for dynstr, strtab + */ + shname = elf_strptr(elf, shstrndx, (size_t) shdr.sh_name); + if (shname != NULL) { + if ((sec_table[i] = strdup(shname)) == NULL) { + warn("strdup"); + goto next_cmd; + } + if (!strncmp(shname, ".dynstr", 7)) { + dynndx = elf_ndxscn(scn); + if (dynndx == SHN_UNDEF) { + warnx("%s: elf_ndxscn failed: %s", + OBJNAME, elf_errmsg(-1)); + goto next_cmd; + } + } + if (!strncmp(shname, ".strtab", 7)) { + strndx = elf_ndxscn(scn); + if (strndx == SHN_UNDEF) { + warnx("%s: elf_ndxscn failed: %s", + OBJNAME, elf_errmsg(-1)); + goto next_cmd; + } + } + } else { + sec_table[i] = strdup("*UND*"); + if (sec_table[i] == NULL) { + warn("strdup"); + goto next_cmd; + } + } + + + if (is_sec_text(&shdr)) + type_table[i] = 'T'; + else if (is_sec_data(&shdr)) { + if (is_sec_readonly(&shdr)) + type_table[i] = 'R'; + else + type_table[i] = 'D'; + } else if (is_sec_nobits(&shdr)) + type_table[i] = 'B'; + else if (is_sec_debug(shname)) + type_table[i] = 'N'; + else if (is_sec_readonly(&shdr) && !is_sec_nobits(&shdr)) + type_table[i] = 'n'; + } + + print_header(filename, objname); + + if ((dynndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_DYN) || + (strndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_SYM)) { + warnx("%s: no symbols", OBJNAME); + /* This is not an error case */ + goto next_cmd; + } + + STAILQ_INIT(&list_head); + + if (!nm_opts.debug_line) + goto process_sym; + + /* + * Collect dwarf line number information. + */ + + if (dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &de) != + DW_DLV_OK) { + warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de)); + goto process_sym; + } + + line_info = malloc(sizeof(struct line_info_head)); + func_info = malloc(sizeof(struct func_info_head)); + var_info = malloc(sizeof(struct var_info_head)); + if (line_info == NULL || func_info == NULL || var_info == NULL) { + warn("malloc"); + (void) dwarf_finish(dbg, &de); + goto process_sym; + } + SLIST_INIT(line_info); + SLIST_INIT(func_info); + SLIST_INIT(var_info); + + while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, + &de)) == DW_DLV_OK) { + die = NULL; + while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", + dwarf_errmsg(de)); + continue; + } + /* XXX: What about DW_TAG_partial_unit? */ + if (tag == DW_TAG_compile_unit) + break; + } + if (die == NULL) { + warnx("could not find DW_TAG_compile_unit die"); + continue; + } + + /* Retrieve source file list. */ + ret = dwarf_srcfiles(die, &src_files, &filecount, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_srclines: %s", dwarf_errmsg(de)); + if (ret != DW_DLV_OK) + continue; + + /* + * Retrieve line number information from .debug_line section. + */ + + ret = dwarf_srclines(die, &lbuf, &lcount, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_srclines: %s", dwarf_errmsg(de)); + if (ret != DW_DLV_OK) + goto line_attr; + for (i = 0; (Dwarf_Signed) i < lcount; i++) { + if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { + warnx("dwarf_lineaddr: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_lineno(lbuf[i], &lineno, &de)) { + warnx("dwarf_lineno: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_linesrc(lbuf[i], &sfile, &de)) { + warnx("dwarf_linesrc: %s", dwarf_errmsg(de)); + continue; + } + if ((lie = malloc(sizeof(*lie))) == NULL) { + warn("malloc"); + continue; + } + lie->addr = lineaddr; + lie->line = lineno; + lie->file = strdup(sfile); + if (lie->file == NULL) { + warn("strdup"); + free(lie); + continue; + } + SLIST_INSERT_HEAD(line_info, lie, entries); + } + + line_attr: + /* Retrieve line number information from DIEs. */ + search_line_attr(dbg, func_info, var_info, die, src_files, filecount); + } + + (void) dwarf_finish(dbg, &de); + +process_sym: + + p_data.list_num = get_sym(elf, &list_head, shnum, dynndx, strndx, + type_table, (void *) sec_table, shnum); + + if (p_data.list_num == 0) + goto next_cmd; + + p_data.headp = &list_head; + p_data.sh_num = shnum; + p_data.t_table = type_table; + p_data.s_table = (void *) sec_table; + p_data.filename = filename; + p_data.objname = objname; + + sym_list_print(&p_data, func_info, var_info, line_info); + +next_cmd: + if (nm_opts.debug_line) { + if (func_info != NULL) { + while (!SLIST_EMPTY(func_info)) { + func = SLIST_FIRST(func_info); + SLIST_REMOVE_HEAD(func_info, entries); + free(func->file); + free(func->name); + free(func); + } + free(func_info); + func_info = NULL; + } + if (var_info != NULL) { + while (!SLIST_EMPTY(var_info)) { + var = SLIST_FIRST(var_info); + SLIST_REMOVE_HEAD(var_info, entries); + free(var->file); + free(var->name); + free(var); + } + free(var_info); + var_info = NULL; + } + if (line_info != NULL) { + while (!SLIST_EMPTY(line_info)) { + lie = SLIST_FIRST(line_info); + SLIST_REMOVE_HEAD(line_info, entries); + free(lie->file); + free(lie); + } + free(line_info); + line_info = NULL; + } + } + + if (sec_table != NULL) + for (i = 0; i < shnum; ++i) + free(sec_table[i]); + free(sec_table); + free(type_table); + + sym_list_dest(&list_head); + + return (rtn); + +#undef OBJNAME +} + +static int +read_object(const char *filename) +{ + Elf *elf, *arf; + Elf_Cmd elf_cmd; + Elf_Kind kind; + int fd, rtn, e_err; + + assert(filename != NULL && "filename is null"); + + if ((fd = open(filename, O_RDONLY)) == -1) { + warn("'%s'", filename); + return (1); + } + + elf_cmd = ELF_C_READ; + if ((arf = elf_begin(fd, elf_cmd, (Elf *) NULL)) == NULL) { + if ((e_err = elf_errno()) != 0) + warnx("elf_begin error: %s", elf_errmsg(e_err)); + else + warnx("elf_begin error"); + close(fd); + return (1); + } + + assert(arf != NULL && "arf is null."); + + rtn = 0; + if ((kind = elf_kind(arf)) == ELF_K_NONE) { + warnx("%s: File format not recognized", filename); + elf_end(arf); + close(fd); + return (1); + } + if (kind == ELF_K_AR) { + if (nm_opts.print_name == PRINT_NAME_MULTI && + nm_opts.elem_print_fn == sym_elem_print_all) + printf("\n%s:\n", filename); + if (nm_opts.print_armap == true) + print_ar_index(fd, arf); + } + + while ((elf = elf_begin(fd, elf_cmd, arf)) != NULL) { + rtn |= read_elf(elf, filename, kind); + + /* + * If file is not archive, elf_next return ELF_C_NULL and + * stop the loop. + */ + elf_cmd = elf_next(elf); + elf_end(elf); + } + + elf_end(arf); + close(fd); + + return (rtn); +} + +static int +read_files(int argc, char **argv) +{ + int rtn = 0; + + if (argc < 0 || argv == NULL) + return (1); + + if (argc == 0) + rtn |= read_object(nm_info.def_filename); + else { + if (nm_opts.print_name == PRINT_NAME_NONE && argc > 1) + nm_opts.print_name = PRINT_NAME_MULTI; + while (argc > 0) { + rtn |= read_object(*argv); + --argc; + ++argv; + } + } + + return (rtn); +} + +static void +print_lineno(struct sym_entry *ep, struct func_info_head *func_info, + struct var_info_head *var_info, struct line_info_head *line_info) +{ + struct func_info_entry *func; + struct var_info_entry *var; + struct line_info_entry *lie; + + /* For function symbol, search the function line information list. */ + if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) { + SLIST_FOREACH(func, func_info, entries) { + if (!strcmp(ep->name, func->name) && + ep->sym->st_value >= func->lowpc && + ep->sym->st_value < func->highpc) { + printf("\t%s:%" PRIu64, func->file, func->line); + return; + } + } + } + + /* For variable symbol, search the variable line information list. */ + if ((ep->sym->st_info & 0xf) == STT_OBJECT && var_info != NULL) { + SLIST_FOREACH(var, var_info, entries) { + if (!strcmp(ep->name, var->name) && + ep->sym->st_value == var->addr) { + printf("\t%s:%" PRIu64, var->file, var->line); + return; + } + } + } + + /* Otherwise search line number information the .debug_line section. */ + if (line_info != NULL) { + SLIST_FOREACH(lie, line_info, entries) { + if (ep->sym->st_value == lie->addr) { + printf("\t%s:%" PRIu64, lie->file, lie->line); + return; + } + } + } +} + +static void +set_opt_value_print_fn(enum radix t) +{ + + switch (t) { + case RADIX_OCT: + nm_opts.value_print_fn = &sym_value_oct_print; + nm_opts.size_print_fn = &sym_size_oct_print; + + break; + case RADIX_DEC: + nm_opts.value_print_fn = &sym_value_dec_print; + nm_opts.size_print_fn = &sym_size_dec_print; + + break; + case RADIX_HEX: + default : + nm_opts.value_print_fn = &sym_value_hex_print; + nm_opts.size_print_fn = &sym_size_hex_print; + } + + assert(nm_opts.value_print_fn != NULL && + "nm_opts.value_print_fn is null"); +} + +static void +sym_elem_print_all(char type, const char *sec, const GElf_Sym *sym, + const char *name) +{ + + if (sec == NULL || sym == NULL || name == NULL || + nm_opts.value_print_fn == NULL) + return; + + if (IS_UNDEF_SYM_TYPE(type)) { + if (nm_opts.t == RADIX_HEX && nm_elfclass == ELFCLASS32) + printf("%-8s", ""); + else + printf("%-16s", ""); + } else { + switch ((nm_opts.sort_fn == & cmp_size ? 2 : 0) + + nm_opts.print_size) { + case 3: + if (sym->st_size != 0) { + nm_opts.value_print_fn(sym); + printf(" "); + nm_opts.size_print_fn(sym); + } + break; + + case 2: + if (sym->st_size != 0) + nm_opts.size_print_fn(sym); + break; + + case 1: + nm_opts.value_print_fn(sym); + if (sym->st_size != 0) { + printf(" "); + nm_opts.size_print_fn(sym); + } + break; + + case 0: + default: + nm_opts.value_print_fn(sym); + } + } + + printf(" %c ", type); + PRINT_DEMANGLED_NAME("%s", name); +} + +static void +sym_elem_print_all_portable(char type, const char *sec, const GElf_Sym *sym, + const char *name) +{ + + if (sec == NULL || sym == NULL || name == NULL || + nm_opts.value_print_fn == NULL) + return; + + PRINT_DEMANGLED_NAME("%s", name); + printf(" %c ", type); + if (!IS_UNDEF_SYM_TYPE(type)) { + nm_opts.value_print_fn(sym); + printf(" "); + if (sym->st_size != 0) + nm_opts.size_print_fn(sym); + } else + printf(" "); +} + +static void +sym_elem_print_all_sysv(char type, const char *sec, const GElf_Sym *sym, + const char *name) +{ + + if (sec == NULL || sym == NULL || name == NULL || + nm_opts.value_print_fn == NULL) + return; + + PRINT_DEMANGLED_NAME("%-20s|", name); + if (IS_UNDEF_SYM_TYPE(type)) + printf(" "); + else + nm_opts.value_print_fn(sym); + + printf("| %c |", type); + + switch (sym->st_info & 0xf) { + case STT_OBJECT: + printf("%18s|", "OBJECT"); + break; + + case STT_FUNC: + printf("%18s|", "FUNC"); + break; + + case STT_SECTION: + printf("%18s|", "SECTION"); + break; + + case STT_FILE: + printf("%18s|", "FILE"); + break; + + case STT_LOPROC: + printf("%18s|", "LOPROC"); + break; + + case STT_HIPROC: + printf("%18s|", "HIPROC"); + break; + + case STT_NOTYPE: + default: + printf("%18s|", "NOTYPE"); + }; + + if (sym->st_size != 0) + nm_opts.size_print_fn(sym); + else + printf(" "); + + printf("| |%s", sec); +} + +static int +sym_elem_def(char type, const GElf_Sym *sym, const char *name) +{ + + assert(IS_SYM_TYPE((unsigned char) type)); + + UNUSED(sym); + UNUSED(name); + + return (!IS_UNDEF_SYM_TYPE((unsigned char) type)); +} + +static int +sym_elem_global(char type, const GElf_Sym *sym, const char *name) +{ + + assert(IS_SYM_TYPE((unsigned char) type)); + + UNUSED(sym); + UNUSED(name); + + /* weak symbols resemble global. */ + return (isupper((unsigned char) type) || type == 'w'); +} + +static int +sym_elem_global_static(char type, const GElf_Sym *sym, const char *name) +{ + unsigned char info; + + assert(sym != NULL); + + UNUSED(type); + UNUSED(name); + + info = sym->st_info >> 4; + + return (info == STB_LOCAL || + info == STB_GLOBAL || + info == STB_WEAK); +} + +static int +sym_elem_nondebug(char type, const GElf_Sym *sym, const char *name) +{ + + assert(sym != NULL); + + UNUSED(type); + UNUSED(name); + + if (sym->st_value == 0 && (sym->st_info & 0xf) == STT_FILE) + return (0); + if (sym->st_name == 0) + return (0); + + return (1); +} + +static int +sym_elem_nonzero_size(char type, const GElf_Sym *sym, const char *name) +{ + + assert(sym != NULL); + + UNUSED(type); + UNUSED(name); + + return (sym->st_size > 0); +} + +static int +sym_elem_undef(char type, const GElf_Sym *sym, const char *name) +{ + + assert(IS_SYM_TYPE((unsigned char) type)); + + UNUSED(sym); + UNUSED(name); + + return (IS_UNDEF_SYM_TYPE((unsigned char) type)); +} + +static void +sym_list_dest(struct sym_head *headp) +{ + struct sym_entry *ep, *ep_n; + + if (headp == NULL) + return; + + ep = STAILQ_FIRST(headp); + while (ep != NULL) { + ep_n = STAILQ_NEXT(ep, sym_entries); + free(ep->sym); + free(ep->name); + free(ep); + ep = ep_n; + } +} + +static int +sym_list_insert(struct sym_head *headp, const char *name, const GElf_Sym *sym) +{ + struct sym_entry *e; + + if (headp == NULL || name == NULL || sym == NULL) + return (0); + if ((e = malloc(sizeof(struct sym_entry))) == NULL) { + warn("malloc"); + return (0); + } + if ((e->name = strdup(name)) == NULL) { + warn("strdup"); + free(e); + return (0); + } + if ((e->sym = malloc(sizeof(GElf_Sym))) == NULL) { + warn("malloc"); + free(e->name); + free(e); + return (0); + } + + memcpy(e->sym, sym, sizeof(GElf_Sym)); + + /* Display size instead of value for common symbol. */ + if (sym->st_shndx == SHN_COMMON) + e->sym->st_value = sym->st_size; + + STAILQ_INSERT_TAIL(headp, e, sym_entries); + + return (1); +} + +/* If file has not .debug_info, line_info will be NULL */ +static void +sym_list_print(struct sym_print_data *p, struct func_info_head *func_info, + struct var_info_head *var_info, struct line_info_head *line_info) +{ + struct sym_entry *e_v; + size_t si; + int i; + + if (p == NULL || CHECK_SYM_PRINT_DATA(p)) + return; + if ((e_v = sym_list_sort(p)) == NULL) + return; + if (nm_opts.sort_reverse == false) + for (si = 0; si != p->list_num; ++si) + sym_list_print_each(&e_v[si], p, func_info, var_info, + line_info); + else + for (i = p->list_num - 1; i != -1; --i) + sym_list_print_each(&e_v[i], p, func_info, var_info, + line_info); + + free(e_v); +} + +/* If file has not .debug_info, line_info will be NULL */ +static void +sym_list_print_each(struct sym_entry *ep, struct sym_print_data *p, + struct func_info_head *func_info, struct var_info_head *var_info, + struct line_info_head *line_info) +{ + const char *sec; + char type; + + if (ep == NULL || CHECK_SYM_PRINT_DATA(p)) + return; + + assert(ep->name != NULL); + assert(ep->sym != NULL); + + type = get_sym_type(ep->sym, p->t_table); + + if (nm_opts.print_name == PRINT_NAME_FULL) { + printf("%s", p->filename); + if (nm_opts.elem_print_fn == &sym_elem_print_all_portable) { + if (p->objname != NULL) + printf("[%s]", p->objname); + printf(": "); + } else { + if (p->objname != NULL) + printf(":%s", p->objname); + printf(":"); + } + } + + switch (ep->sym->st_shndx) { + case SHN_LOPROC: + /* LOPROC or LORESERVE */ + sec = "*LOPROC*"; + break; + case SHN_HIPROC: + sec = "*HIPROC*"; + break; + case SHN_LOOS: + sec = "*LOOS*"; + break; + case SHN_HIOS: + sec = "*HIOS*"; + break; + case SHN_ABS: + sec = "*ABS*"; + break; + case SHN_COMMON: + sec = "*COM*"; + break; + case SHN_HIRESERVE: + /* HIRESERVE or XINDEX */ + sec = "*HIRESERVE*"; + break; + default: + if (ep->sym->st_shndx > p->sh_num) + return; + sec = p->s_table[ep->sym->st_shndx]; + break; + }; + + nm_opts.elem_print_fn(type, sec, ep->sym, ep->name); + + if (nm_opts.debug_line == true && !IS_UNDEF_SYM_TYPE(type)) + print_lineno(ep, func_info, var_info, line_info); + + printf("\n"); +} + +static struct sym_entry * +sym_list_sort(struct sym_print_data *p) +{ + struct sym_entry *ep, *e_v; + int idx; + + if (p == NULL || CHECK_SYM_PRINT_DATA(p)) + return (NULL); + + if ((e_v = malloc(sizeof(struct sym_entry) * p->list_num)) == NULL) { + warn("malloc"); + return (NULL); + } + + idx = 0; + STAILQ_FOREACH(ep, p->headp, sym_entries) { + if (ep->name != NULL && ep->sym != NULL) { + e_v[idx].name = ep->name; + e_v[idx].sym = ep->sym; + ++idx; + } + } + + assert((size_t)idx == p->list_num); + + if (nm_opts.sort_fn != &cmp_none) { + nm_print_data = p; + assert(nm_print_data != NULL); + qsort(e_v, p->list_num, sizeof(struct sym_entry), + nm_opts.sort_fn); + } + + return (e_v); +} + +static void +sym_size_oct_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + printf("%016" PRIo64, sym->st_size); +} + +static void +sym_size_hex_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + if (nm_elfclass == ELFCLASS32) + printf("%08" PRIx64, sym->st_size); + else + printf("%016" PRIx64, sym->st_size); +} + +static void +sym_size_dec_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + printf("%016" PRId64, sym->st_size); +} + +static void +sym_value_oct_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + printf("%016" PRIo64, sym->st_value); +} + +static void +sym_value_hex_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + if (nm_elfclass == ELFCLASS32) + printf("%08" PRIx64, sym->st_value); + else + printf("%016" PRIx64, sym->st_value); +} + +static void +sym_value_dec_print(const GElf_Sym *sym) +{ + + assert(sym != NULL && "sym is null"); + printf("%016" PRId64, sym->st_value); +} + +static void +usage(int exitcode) +{ + + printf("Usage: %s [options] file ...\ +\n Display symbolic information in file.\n\ +\n Options: \ +\n -A, --print-file-name Write the full pathname or library name of an\ +\n object on each line.\ +\n -a, --debug-syms Display all symbols include debugger-only\ +\n symbols.", nm_info.name); + printf("\ +\n -B Equivalent to specifying \"--format=bsd\".\ +\n -C, --demangle[=style] Decode low-level symbol names.\ +\n --no-demangle Do not demangle low-level symbol names.\ +\n -D, --dynamic Display only dynamic symbols.\ +\n -e Display only global and static symbols."); + printf("\ +\n -f Produce full output (default).\ +\n --format=format Display output in specific format. Allowed\ +\n formats are: \"bsd\", \"posix\" and \"sysv\".\ +\n -g Display only global symbol information.\ +\n -h, --help Show this help message.\ +\n -l, --line-numbers Display filename and linenumber using\ +\n debugging information.\ +\n -n, --numeric-sort Sort symbols numerically by value."); + printf("\ +\n -o Write numeric values in octal. Equivalent to\ +\n specifying \"-t o\".\ +\n -p, --no-sort Do not sort symbols.\ +\n -P Write information in a portable output format.\ +\n Equivalent to specifying \"--format=posix\".\ +\n -r, --reverse-sort Reverse the order of the sort.\ +\n -S, --print-size Print symbol sizes instead values.\ +\n -s, --print-armap Include an index of archive members.\ +\n --size-sort Sort symbols by size."); + printf("\ +\n -t, --radix=format Write each numeric value in the specified\ +\n format:\ +\n d In decimal,\ +\n o In octal,\ +\n x In hexadecimal."); + printf("\ +\n -u, --undefined-only Display only undefined symbols.\ +\n --defined-only Display only defined symbols.\ +\n -V, --version Show the version identifier for %s.\ +\n -v Sort output by value.\ +\n -x Write numeric values in hexadecimal.\ +\n Equivalent to specifying \"-t x\".", + nm_info.name); + printf("\n\ +\n The default options are: output in bsd format, use a hexadecimal radix,\ +\n sort by symbol name, do not demangle names.\n"); + + exit(exitcode); +} + +/* + * Display symbolic information in file. + * Return 0 at success, >0 at failed. + */ +int +main(int argc, char **argv) +{ + int rtn; + + global_init(); + get_opt(argc, argv); + rtn = read_files(argc - optind, argv + optind); + global_dest(); + + exit(rtn); +} diff --git a/contrib/elftoolchain/size/Makefile b/contrib/elftoolchain/size/Makefile new file mode 100644 index 000000000000..6d46d634d462 --- /dev/null +++ b/contrib/elftoolchain/size/Makefile @@ -0,0 +1,11 @@ +# $Id: Makefile 2043 2011-10-23 14:49:16Z jkoshy $ + +TOP= .. + +PROG= size +WARNS?= 6 +LDADD= -lelftc -lelf +DPADD= ${LIBELFTC} ${LIBELF} + +.include "${TOP}/mk/elftoolchain.prog.mk" + diff --git a/contrib/elftoolchain/size/size.1 b/contrib/elftoolchain/size/size.1 new file mode 100644 index 000000000000..70f3bfdcdf05 --- /dev/null +++ b/contrib/elftoolchain/size/size.1 @@ -0,0 +1,257 @@ +.\" Copyright (c) 2007 S.Sam Arun Raj +.\" Copyright (c) 2008,2011 Joseph Koshy +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: size.1 2043 2011-10-23 14:49:16Z jkoshy $ +.\" +.Dd August 25, 2011 +.Dt SIZE 1 +.Os +.Sh NAME +.Nm size +.Nd "display section sizes and total size of ELF objects" +.Sh SYNOPSIS +.Nm +.Op Fl -format= Ns Ar format +.Op Fl -help +.Op Fl -radix= Ns Ar radix +.Op Fl -totals +.Op Fl -version +.Op Fl ABVdhotx +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility +lists the sizes of ELF sections, and optionally the total size, for +each input +.Ar file +specified on the command line. +The +.Nm +utility can operate on ELF objects, on +.Xr ar 1 +archives containing ELF objects, and on core dumps. +If no file name is specified on the command-line, +.Pa a.out +is assumed. +.Pp +The +.Nm +utility recognized the following options: +.Bl -tag -width indent +.It Fl -format= Ns Ar format +Display output using the format specified by argument +.Ar format . +Supported values for this argument are: +.Sq berkeley +and +.Sq sysv . +The default output format is +.Sq berkeley . +See +.Sx Display Formats +below for more information. +.It Fl -help +Display a help message and exit. +.It Fl -radix= Ns Ar radix +Display numeric values using the radix specified by argument +.Ar radix . +Supported values for +.Ar radix +are 8, 10 and 16. +The default radix is 10. +.It Fl -totals +Shows cumulative totals of section sizes from all objects. +This option is ignored for System V style output. +.It Fl -version +Display a version identifier and exit. +.It Fl A +Equivalent to specifying option +.Fl -format= Ns Ar sysv . +.It Fl B +Equivalent to specifying option +.Fl -format= Ns Ar berkeley . +.It Fl V +Equivalent to specifying option +.Fl -version . +.It Fl d +Equivalent to specifying option +.Fl -radix= Ns Ar 10 . +.It Fl h +Equivalent to specifying option +.Fl -help . +.It Fl o +Equivalent to specifying option +.Fl -radix= Ns Ar 8 . +.It Fl t +Equivalent to specifying option +.Fl -totals . +.It Fl x +Equivalent to specifying option +.Fl -radix= Ns Ar 16 . +.El +.Sh DISPLAY FORMATS +.Ss Berkeley Style Output +If +.Sq berkeley +style output is in effect, an initial header line naming fields will +be output, followed by one line of output for each ELF object specified +on the command line or found in an archive. +.Pp +Each line will contain the following whitespace separated fields +in order: +.Bl -enum -compact +.It +The size of the text segment in the object. +.It +The size of the data segment in the object. +.It +The size of the +.Sq bss +segment in the object. +.It +The total size of the object in either decimal or octal. +Decimal output is used if the specified output radix for numeric values +is 10 or 16. +Octal output is used if the radix being used for numeric values +is 8. +.It +The total size of the object in hexadecimal. +.It +The file name of the object. +.El +.Pp +If option +.Fl -totals +was specified, an additional line in the same format as above will be +output at the end containing the sum of the respective fields. +The file name field for the line will contain the string +.Sq (TOTALS) . +.Ss System V Style Output +If System V style output is selected, +.Nm +will output the following information for each object: +.Bl -enum -compact +.It +The name of the object followed by a colon. +.It +A header line containing the names of fields of subsequent lines. +.It +One line per section present in the object. +Each line has three fields: +.Bl -enum -compact +.It +The name of the section. +.It +Its size, in the selected radix for numeric values. +.It +The address associated with the section, in the selected numeric radix. +.El +.It +A line whose section name field contains the string +.Sq Total +and whose size field contains the sum of all reported section sizes. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +To display the section sizes for +.Pa /bin/ls +use: +.Bd -literal +$ size /bin/ls +text data bss dec hex filename +20975 540 392 21907 5593 /bin/ls +.Ed +.Pp +To display sizes and total for +.Pa /bin/ls +and +.Pa /bin/dd +in hexadecimal, use: +.Bd -literal +$ size -tx /bin/ls /bin/dd +text data bss dec hex filename +0x51ef 0x21c 0x188 21907 5593 /bin/ls +0x3df5 0x170 0x200 16741 4165 /bin/dd +0x8fe4 0x38c 0x388 38648 96f8 (TOTALS) +.Ed +.Pp +To display section sizes for +.Pa /bin/ls +in System V format use: +.Bd -literal +$ size -A /bin/ls +/bin/ls : +section size addr +\&.interp 21 4194704 +\&.note.ABI-tag 24 4194728 +\&.hash 624 4194752 +\&.dynsym 2088 4195376 +\&.dynstr 810 4197464 +\&.rela.dyn 120 4198280 +\&.rela.plt 1656 4198400 +\&.init 19 4200056 +\&.plt 1120 4200076 +\&.text 15224 4201200 +\&.fini 14 4216424 +\&.rodata 1472 4216448 +\&.data 80 5267456 +\&.eh_frame 1624 5267536 +\&.dynamic 384 5269160 +\&.ctors 16 5269544 +\&.dtors 16 5269560 +\&.jcr 8 5269576 +\&.got 576 5269584 +\&.bss 528 5270176 +\&.comment 686 0 +Total 27110 +.Ed +.Sh SEE ALSO +.Xr ar 1 , +.Xr nm 1 , +.Xr objdump 1 , +.Xr readelf 1 , +.Xr strings 1 , +.Xr elf 3 , +.Xr gelf 3 +.Rs +.%A "AT&T Unix Systems Labs" +.%T "System V Application Binary Interface" +.%O http://www.sco.com/developers/gabi/ +.Re +.Sh HISTORY +The +.Nm +utility first appeared in +.At v6 . +.Sh AUTHORS +.An -nosplit +The +.Nm +utility was re-written by +.An S. Sam Arun Raj Aq samarunraj@gmail.com +This manual page was written by +.An S. Sam Arun Raj Aq samarunraj@gmail.com diff --git a/contrib/elftoolchain/size/size.c b/contrib/elftoolchain/size/size.c new file mode 100644 index 000000000000..c5c5b64cb0d0 --- /dev/null +++ b/contrib/elftoolchain/size/size.c @@ -0,0 +1,914 @@ +/*- + * Copyright (c) 2007 S.Sam Arun Raj + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: size.c 2350 2011-12-19 10:20:06Z jkoshy $"); + +#define BUF_SIZE 1024 +#define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1)) +#define SIZE_VERSION_STRING "size 1.0" + +enum return_code { + RETURN_OK, + RETURN_NOINPUT, + RETURN_DATAERR, + RETURN_USAGE +}; + +enum output_style { + STYLE_BERKELEY, + STYLE_SYSV +}; + +enum radix_style { + RADIX_OCTAL, + RADIX_DECIMAL, + RADIX_HEX +}; + +static uint64_t bss_size, data_size, text_size, total_size; +static uint64_t bss_size_total, data_size_total, text_size_total; +static int show_totals; +static int size_option; +static enum radix_style radix = RADIX_DECIMAL; +static enum output_style style = STYLE_BERKELEY; +static const char *default_args[2] = { "a.out", NULL }; + +static struct { + int row; + int col; + int *width; + char ***tbl; +} *tb; + +enum { + OPT_FORMAT, + OPT_RADIX +}; + +static struct option size_longopts[] = { + { "format", required_argument, &size_option, OPT_FORMAT }, + { "help", no_argument, NULL, 'h' }, + { "radix", required_argument, &size_option, OPT_RADIX }, + { "totals", no_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + +static void berkeley_calc(GElf_Shdr *); +static void berkeley_footer(const char *, const char *, const char *); +static void berkeley_header(void); +static void berkeley_totals(void); +static int handle_core(char const *, Elf *elf, GElf_Ehdr *); +static void handle_core_note(Elf *, GElf_Ehdr *, GElf_Phdr *, char **); +static int handle_elf(char const *); +static void handle_phdr(Elf *, GElf_Ehdr *, GElf_Phdr *, uint32_t, + const char *); +static void show_version(void); +static void sysv_header(const char *, Elf_Arhdr *); +static void sysv_footer(void); +static void sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *); +static void usage(void); +static void tbl_new(int); +static void tbl_print(const char *, int); +static void tbl_print_num(uint64_t, enum radix_style, int); +static void tbl_append(void); +static void tbl_flush(void); + +/* + * size utility using elf(3) and gelf(3) API to list section sizes and + * total in elf files. Supports only elf files (core dumps in elf + * included) that can be opened by libelf, other formats are not supported. + */ +int +main(int argc, char **argv) +{ + int ch, r, rc; + const char **files, *fn; + + rc = RETURN_OK; + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "ELF library initialization failed: %s", + elf_errmsg(-1)); + + while ((ch = getopt_long(argc, argv, "ABVdhotx", size_longopts, + NULL)) != -1) + switch((char)ch) { + case 'A': + style = STYLE_SYSV; + break; + case 'B': + style = STYLE_BERKELEY; + break; + case 'V': + show_version(); + break; + case 'd': + radix = RADIX_DECIMAL; + break; + case 'o': + radix = RADIX_OCTAL; + break; + case 't': + show_totals = 1; + break; + case 'x': + radix = RADIX_HEX; + break; + case 0: + switch (size_option) { + case OPT_FORMAT: + if (*optarg == 's' || *optarg == 'S') + style = STYLE_SYSV; + else if (*optarg == 'b' || *optarg == 'B') + style = STYLE_BERKELEY; + else { + warnx("unrecognized format \"%s\".", + optarg); + usage(); + } + break; + case OPT_RADIX: + r = strtol(optarg, NULL, 10); + if (r == 8) + radix = RADIX_OCTAL; + else if (r == 10) + radix = RADIX_DECIMAL; + else if (r == 16) + radix = RADIX_HEX; + else { + warnx("unsupported radix \"%s\".", + optarg); + usage(); + } + break; + default: + err(EXIT_FAILURE, "Error in option handling."); + /*NOTREACHED*/ + } + break; + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + files = (argc == 0) ? default_args : (void *) argv; + + while ((fn = *files) != NULL) { + rc = handle_elf(fn); + if (rc != RETURN_OK) + warnx(rc == RETURN_NOINPUT ? + "'%s': No such file" : + "%s: File format not recognized", fn); + files++; + } + if (style == STYLE_BERKELEY) { + if (show_totals) + berkeley_totals(); + tbl_flush(); + } + return (rc); +} + +static Elf_Data * +xlatetom(Elf *elf, GElf_Ehdr *elfhdr, void *_src, void *_dst, + Elf_Type type, size_t size) +{ + Elf_Data src, dst; + + src.d_buf = _src; + src.d_type = type; + src.d_version = elfhdr->e_version; + src.d_size = size; + dst.d_buf = _dst; + dst.d_version = elfhdr->e_version; + dst.d_size = size; + return (gelf_xlatetom(elf, &dst, &src, elfhdr->e_ident[EI_DATA])); +} + +#define NOTE_OFFSET_32(nhdr, namesz, offset) \ + ((char *)nhdr + sizeof(Elf32_Nhdr) + \ + ELF_ALIGN((int32_t)namesz, 4) + offset) + +#define NOTE_OFFSET_64(nhdr, namesz, offset) \ + ((char *)nhdr + sizeof(Elf32_Nhdr) + \ + ELF_ALIGN((int32_t)namesz, 8) + offset) + +#define PID32(nhdr, namesz, offset) \ + (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_32(nhdr, \ + namesz, offset))); + +#define PID64(nhdr, namesz, offset) \ + (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_64(nhdr, \ + namesz, offset))); + +#define NEXT_NOTE(elfhdr, descsz, namesz, offset) do { \ + if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { \ + offset += ELF_ALIGN((int32_t)descsz, 4) + \ + sizeof(Elf32_Nhdr) + \ + ELF_ALIGN((int32_t)namesz, 4); \ + } else { \ + offset += ELF_ALIGN((int32_t)descsz, 8) + \ + sizeof(Elf32_Nhdr) + \ + ELF_ALIGN((int32_t)namesz, 8); \ + } \ +} while (0) + +/* + * Parse individual note entries inside a PT_NOTE segment. + */ +static void +handle_core_note(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr, + char **cmd_line) +{ + size_t max_size; + uint64_t raw_size; + GElf_Off offset; + static pid_t pid; + uintptr_t ver; + Elf32_Nhdr *nhdr, nhdr_l; + static int reg_pseudo = 0, reg2_pseudo = 0, regxfp_pseudo = 0; + char buf[BUF_SIZE], *data, *name; + + if (elf == NULL || elfhdr == NULL || phdr == NULL) + return; + + data = elf_rawfile(elf, &max_size); + offset = phdr->p_offset; + while (data != NULL && offset < phdr->p_offset + phdr->p_filesz) { + nhdr = (Elf32_Nhdr *)(uintptr_t)((char*)data + offset); + memset(&nhdr_l, 0, sizeof(Elf32_Nhdr)); + if (!xlatetom(elf, elfhdr, &nhdr->n_type, &nhdr_l.n_type, + ELF_T_WORD, sizeof(Elf32_Word)) || + !xlatetom(elf, elfhdr, &nhdr->n_descsz, &nhdr_l.n_descsz, + ELF_T_WORD, sizeof(Elf32_Word)) || + !xlatetom(elf, elfhdr, &nhdr->n_namesz, &nhdr_l.n_namesz, + ELF_T_WORD, sizeof(Elf32_Word))) + break; + + name = (char *)((char *)nhdr + sizeof(Elf32_Nhdr)); + switch (nhdr_l.n_type) { + case NT_PRSTATUS: { + raw_size = 0; + if (elfhdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD && + nhdr_l.n_namesz == 0x8 && + !strcmp(name,"FreeBSD")) { + if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { + raw_size = (uint64_t)*((uint32_t *) + (uintptr_t)(name + + ELF_ALIGN((int32_t) + nhdr_l.n_namesz, 4) + 8)); + ver = (uintptr_t)NOTE_OFFSET_32(nhdr, + nhdr_l.n_namesz,0); + if (*((int *)ver) == 1) + pid = PID32(nhdr, + nhdr_l.n_namesz, 24); + } else { + raw_size = *((uint64_t *)(uintptr_t) + (name + ELF_ALIGN((int32_t) + nhdr_l.n_namesz, 8) + 16)); + ver = (uintptr_t)NOTE_OFFSET_64(nhdr, + nhdr_l.n_namesz,0); + if (*((int *)ver) == 1) + pid = PID64(nhdr, + nhdr_l.n_namesz, 40); + } + xlatetom(elf, elfhdr, &raw_size, &raw_size, + ELF_T_WORD, sizeof(uint64_t)); + xlatetom(elf, elfhdr, &pid, &pid, ELF_T_WORD, + sizeof(pid_t)); + } + + if (raw_size != 0 && style == STYLE_SYSV) { + (void) snprintf(buf, BUF_SIZE, "%s/%d", + ".reg", pid); + tbl_append(); + tbl_print(buf, 0); + tbl_print_num(raw_size, radix, 1); + tbl_print_num(0, radix, 2); + if (!reg_pseudo) { + tbl_append(); + tbl_print(".reg", 0); + tbl_print_num(raw_size, radix, 1); + tbl_print_num(0, radix, 2); + reg_pseudo = 1; + text_size_total += raw_size; + } + text_size_total += raw_size; + } + } + break; + case NT_FPREGSET: /* same as NT_PRFPREG */ + if (style == STYLE_SYSV) { + (void) snprintf(buf, BUF_SIZE, + "%s/%d", ".reg2", pid); + tbl_append(); + tbl_print(buf, 0); + tbl_print_num(nhdr_l.n_descsz, radix, 1); + tbl_print_num(0, radix, 2); + if (!reg2_pseudo) { + tbl_append(); + tbl_print(".reg2", 0); + tbl_print_num(nhdr_l.n_descsz, radix, + 1); + tbl_print_num(0, radix, 2); + reg2_pseudo = 1; + text_size_total += nhdr_l.n_descsz; + } + text_size_total += nhdr_l.n_descsz; + } + break; + case NT_AUXV: + if (style == STYLE_SYSV) { + tbl_append(); + tbl_print(".auxv", 0); + tbl_print_num(nhdr_l.n_descsz, radix, 1); + tbl_print_num(0, radix, 2); + text_size_total += nhdr_l.n_descsz; + } + break; + case NT_PRXFPREG: + if (style == STYLE_SYSV) { + (void) snprintf(buf, BUF_SIZE, "%s/%d", + ".reg-xfp", pid); + tbl_append(); + tbl_print(buf, 0); + tbl_print_num(nhdr_l.n_descsz, radix, 1); + tbl_print_num(0, radix, 2); + if (!regxfp_pseudo) { + tbl_append(); + tbl_print(".reg-xfp", 0); + tbl_print_num(nhdr_l.n_descsz, radix, + 1); + tbl_print_num(0, radix, 2); + regxfp_pseudo = 1; + text_size_total += nhdr_l.n_descsz; + } + text_size_total += nhdr_l.n_descsz; + } + break; + case NT_PSINFO: + case NT_PRPSINFO: { + /* FreeBSD 64-bit */ + if (nhdr_l.n_descsz == 0x78 && + !strcmp(name,"FreeBSD")) { + *cmd_line = strdup(NOTE_OFFSET_64(nhdr, + nhdr_l.n_namesz, 33)); + /* FreeBSD 32-bit */ + } else if (nhdr_l.n_descsz == 0x6c && + !strcmp(name,"FreeBSD")) { + *cmd_line = strdup(NOTE_OFFSET_32(nhdr, + nhdr_l.n_namesz, 25)); + } + /* Strip any trailing spaces */ + if (*cmd_line != NULL) { + char *s; + + s = *cmd_line + strlen(*cmd_line); + while (s > *cmd_line) { + if (*(s-1) != 0x20) break; + s--; + } + *s = 0; + } + break; + } + case NT_PSTATUS: + case NT_LWPSTATUS: + default: + break; + } + NEXT_NOTE(elfhdr, nhdr_l.n_descsz, nhdr_l.n_namesz, offset); + } +} + +/* + * Handles program headers except for PT_NOTE, when sysv output stlye is + * choosen, prints out the segment name and length. For berkely output + * style only PT_LOAD segments are handled, and text, + * data, bss size is calculated for them. + */ +static void +handle_phdr(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr, + uint32_t idx, const char *name) +{ + uint64_t addr, size; + int split; + char buf[BUF_SIZE]; + + if (elf == NULL || elfhdr == NULL || phdr == NULL) + return; + + size = addr = 0; + split = (phdr->p_memsz > 0) && (phdr->p_filesz > 0) && + (phdr->p_memsz > phdr->p_filesz); + + if (style == STYLE_SYSV) { + (void) snprintf(buf, BUF_SIZE, + "%s%d%s", name, idx, (split ? "a" : "")); + tbl_append(); + tbl_print(buf, 0); + tbl_print_num(phdr->p_filesz, radix, 1); + tbl_print_num(phdr->p_vaddr, radix, 2); + text_size_total += phdr->p_filesz; + if (split) { + size = phdr->p_memsz - phdr->p_filesz; + addr = phdr->p_vaddr + phdr->p_filesz; + (void) snprintf(buf, BUF_SIZE, "%s%d%s", name, + idx, "b"); + text_size_total += phdr->p_memsz - phdr->p_filesz; + tbl_append(); + tbl_print(buf, 0); + tbl_print_num(size, radix, 1); + tbl_print_num(addr, radix, 2); + } + } else { + if (phdr->p_type != PT_LOAD) + return; + if ((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) { + data_size += phdr->p_filesz; + if (split) + data_size += phdr->p_memsz - phdr->p_filesz; + } else { + text_size += phdr->p_filesz; + if (split) + text_size += phdr->p_memsz - phdr->p_filesz; + } + } +} + +/* + * Given a core dump file, this function maps program headers to segments. + */ +static int +handle_core(char const *name, Elf *elf, GElf_Ehdr *elfhdr) +{ + GElf_Phdr phdr; + uint32_t i; + char *core_cmdline; + const char *seg_name; + + if (name == NULL || elf == NULL || elfhdr == NULL) + return (RETURN_DATAERR); + if (elfhdr->e_shnum != 0 || elfhdr->e_type != ET_CORE) + return (RETURN_DATAERR); + + seg_name = core_cmdline = NULL; + if (style == STYLE_SYSV) + sysv_header(name, NULL); + else + berkeley_header(); + + for (i = 0; i < elfhdr->e_phnum; i++) { + if (gelf_getphdr(elf, i, &phdr) != NULL) { + if (phdr.p_type == PT_NOTE) { + handle_phdr(elf, elfhdr, &phdr, i, "note"); + handle_core_note(elf, elfhdr, &phdr, + &core_cmdline); + } else { + switch(phdr.p_type) { + case PT_NULL: + seg_name = "null"; + break; + case PT_LOAD: + seg_name = "load"; + break; + case PT_DYNAMIC: + seg_name = "dynamic"; + break; + case PT_INTERP: + seg_name = "interp"; + break; + case PT_SHLIB: + seg_name = "shlib"; + break; + case PT_PHDR: + seg_name = "phdr"; + break; + case PT_GNU_EH_FRAME: + seg_name = "eh_frame_hdr"; + break; + case PT_GNU_STACK: + seg_name = "stack"; + break; + default: + seg_name = "segment"; + } + handle_phdr(elf, elfhdr, &phdr, i, seg_name); + } + } + } + + if (style == STYLE_BERKELEY) { + if (core_cmdline != NULL) { + berkeley_footer(core_cmdline, name, + "core file invoked as"); + } else { + berkeley_footer(core_cmdline, name, "core file"); + } + } else { + sysv_footer(); + if (core_cmdline != NULL) { + (void) printf(" (core file invoked as %s)\n\n", + core_cmdline); + } else { + (void) printf(" (core file)\n\n"); + } + } + free(core_cmdline); + return (RETURN_OK); +} + +/* + * Given an elf object,ar(1) filename, and based on the output style + * and radix format the various sections and their length will be printed + * or the size of the text, data, bss sections will be printed out. + */ +static int +handle_elf(char const *name) +{ + GElf_Ehdr elfhdr; + GElf_Shdr shdr; + Elf *elf, *elf1; + Elf_Arhdr *arhdr; + Elf_Scn *scn; + Elf_Cmd elf_cmd; + int exit_code, fd; + + if (name == NULL) + return (RETURN_NOINPUT); + + if ((fd = open(name, O_RDONLY, 0)) < 0) + return (RETURN_NOINPUT); + + elf_cmd = ELF_C_READ; + elf1 = elf_begin(fd, elf_cmd, NULL); + while ((elf = elf_begin(fd, elf_cmd, elf1)) != NULL) { + arhdr = elf_getarhdr(elf); + if (elf_kind(elf) == ELF_K_NONE && arhdr == NULL) { + (void) elf_end(elf); + (void) elf_end(elf1); + (void) close(fd); + return (RETURN_DATAERR); + } + if (elf_kind(elf) != ELF_K_ELF || + (gelf_getehdr(elf, &elfhdr) == NULL)) { + elf_cmd = elf_next(elf); + (void) elf_end(elf); + warnx("%s: File format not recognized", + arhdr->ar_name); + continue; + } + /* Core dumps are handled seperately */ + if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { + exit_code = handle_core(name, elf, &elfhdr); + (void) elf_end(elf); + (void) elf_end(elf1); + (void) close(fd); + return (exit_code); + } else { + scn = NULL; + if (style == STYLE_BERKELEY) { + berkeley_header(); + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != NULL) + berkeley_calc(&shdr); + } + } else { + sysv_header(name, arhdr); + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != NULL) + sysv_calc(elf, &elfhdr, &shdr); + } + } + if (style == STYLE_BERKELEY) { + if (arhdr != NULL) { + berkeley_footer(name, arhdr->ar_name, + "ex"); + } else { + berkeley_footer(name, NULL, "ex"); + } + } else { + sysv_footer(); + } + } + elf_cmd = elf_next(elf); + (void) elf_end(elf); + } + (void) elf_end(elf1); + (void) close(fd); + return (RETURN_OK); +} + +/* + * Sysv formatting helper functions. + */ +static void +sysv_header(const char *name, Elf_Arhdr *arhdr) +{ + + text_size_total = 0; + if (arhdr != NULL) + (void) printf("%s (ex %s):\n", arhdr->ar_name, name); + else + (void) printf("%s :\n", name); + tbl_new(3); + tbl_append(); + tbl_print("section", 0); + tbl_print("size", 1); + tbl_print("addr", 2); +} + +static void +sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr) +{ + char *section_name; + + section_name = elf_strptr(elf, elfhdr->e_shstrndx, + (size_t) shdr->sh_name); + if ((shdr->sh_type == SHT_SYMTAB || + shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA || + shdr->sh_type == SHT_REL) && shdr->sh_addr == 0) + return; + tbl_append(); + tbl_print(section_name, 0); + tbl_print_num(shdr->sh_size, radix, 1); + tbl_print_num(shdr->sh_addr, radix, 2); + text_size_total += shdr->sh_size; +} + +static void +sysv_footer(void) +{ + tbl_append(); + tbl_print("Total", 0); + tbl_print_num(text_size_total, radix, 1); + tbl_flush(); + putchar('\n'); +} + +/* + * berkeley style output formatting helper functions. + */ +static void +berkeley_header(void) +{ + static int printed; + + text_size = data_size = bss_size = 0; + if (!printed) { + tbl_new(6); + tbl_append(); + tbl_print("text", 0); + tbl_print("data", 1); + tbl_print("bss", 2); + if (radix == RADIX_OCTAL) + tbl_print("oct", 3); + else + tbl_print("dec", 3); + tbl_print("hex", 4); + tbl_print("filename", 5); + printed = 1; + } +} + +static void +berkeley_calc(GElf_Shdr *shdr) +{ + if (shdr != NULL) { + if (!(shdr->sh_flags & SHF_ALLOC)) + return; + if ((shdr->sh_flags & SHF_ALLOC) && + ((shdr->sh_flags & SHF_EXECINSTR) || + !(shdr->sh_flags & SHF_WRITE))) + text_size += shdr->sh_size; + else if ((shdr->sh_flags & SHF_ALLOC) && + (shdr->sh_flags & SHF_WRITE) && + (shdr->sh_type != SHT_NOBITS)) + data_size += shdr->sh_size; + else + bss_size += shdr->sh_size; + } +} + +static void +berkeley_totals(void) +{ + long unsigned int grand_total; + + grand_total = text_size_total + data_size_total + bss_size_total; + tbl_append(); + tbl_print_num(text_size_total, radix, 0); + tbl_print_num(data_size_total, radix, 1); + tbl_print_num(bss_size_total, radix, 2); + if (radix == RADIX_OCTAL) + tbl_print_num(grand_total, RADIX_OCTAL, 3); + else + tbl_print_num(grand_total, RADIX_DECIMAL, 3); + tbl_print_num(grand_total, RADIX_HEX, 4); +} + +static void +berkeley_footer(const char *name, const char *ar_name, const char *msg) +{ + char buf[BUF_SIZE]; + + total_size = text_size + data_size + bss_size; + if (show_totals) { + text_size_total += text_size; + bss_size_total += bss_size; + data_size_total += data_size; + } + + tbl_append(); + tbl_print_num(text_size, radix, 0); + tbl_print_num(data_size, radix, 1); + tbl_print_num(bss_size, radix, 2); + if (radix == RADIX_OCTAL) + tbl_print_num(total_size, RADIX_OCTAL, 3); + else + tbl_print_num(total_size, RADIX_DECIMAL, 3); + tbl_print_num(total_size, RADIX_HEX, 4); + if (ar_name != NULL && name != NULL) + (void) snprintf(buf, BUF_SIZE, "%s (%s %s)", ar_name, msg, + name); + else if (ar_name != NULL && name == NULL) + (void) snprintf(buf, BUF_SIZE, "%s (%s)", ar_name, msg); + else + (void) snprintf(buf, BUF_SIZE, "%s", name); + tbl_print(buf, 5); +} + + +static void +tbl_new(int col) +{ + + assert(tb == NULL); + assert(col > 0); + if ((tb = calloc(1, sizeof(*tb))) == NULL) + err(EXIT_FAILURE, "calloc"); + if ((tb->tbl = calloc(col, sizeof(*tb->tbl))) == NULL) + err(EXIT_FAILURE, "calloc"); + if ((tb->width = calloc(col, sizeof(*tb->width))) == NULL) + err(EXIT_FAILURE, "calloc"); + tb->col = col; + tb->row = 0; +} + +static void +tbl_print(const char *s, int col) +{ + int len; + + assert(tb != NULL && tb->col > 0 && tb->row > 0 && col < tb->col); + assert(s != NULL && tb->tbl[col][tb->row - 1] == NULL); + if ((tb->tbl[col][tb->row - 1] = strdup(s)) == NULL) + err(EXIT_FAILURE, "strdup"); + len = strlen(s); + if (len > tb->width[col]) + tb->width[col] = len; +} + +static void +tbl_print_num(uint64_t num, enum radix_style rad, int col) +{ + char buf[BUF_SIZE]; + + (void) snprintf(buf, BUF_SIZE, (rad == RADIX_DECIMAL ? "%ju" : + ((rad == RADIX_OCTAL) ? "0%jo" : "0x%jx")), (uintmax_t) num); + tbl_print(buf, col); +} + +static void +tbl_append(void) +{ + int i; + + assert(tb != NULL && tb->col > 0); + tb->row++; + for (i = 0; i < tb->col; i++) { + tb->tbl[i] = realloc(tb->tbl[i], sizeof(*tb->tbl[i]) * tb->row); + if (tb->tbl[i] == NULL) + err(EXIT_FAILURE, "realloc"); + tb->tbl[i][tb->row - 1] = NULL; + } +} + +static void +tbl_flush(void) +{ + const char *str; + int i, j; + + if (tb == NULL) + return; + + assert(tb->col > 0); + for (i = 0; i < tb->row; i++) { + if (style == STYLE_BERKELEY) + printf(" "); + for (j = 0; j < tb->col; j++) { + str = (tb->tbl[j][i] != NULL ? tb->tbl[j][i] : ""); + if (style == STYLE_SYSV && j == 0) + printf("%-*s", tb->width[j], str); + else if (style == STYLE_BERKELEY && j == tb->col - 1) + printf("%s", str); + else + printf("%*s", tb->width[j], str); + if (j == tb->col -1) + putchar('\n'); + else + printf(" "); + } + } + + for (i = 0; i < tb->col; i++) { + for (j = 0; j < tb->row; j++) { + if (tb->tbl[i][j]) + free(tb->tbl[i][j]); + } + free(tb->tbl[i]); + } + free(tb->tbl); + free(tb->width); + free(tb); + tb = NULL; +} + +#define USAGE_MESSAGE "\ +Usage: %s [options] file ...\n\ + Display sizes of ELF sections.\n\n\ + Options:\n\ + --format=format Display output in specified format. Supported\n\ + values are `berkeley' and `sysv'.\n\ + --help Display this help message and exit.\n\ + --radix=radix Display numeric values in the specified radix.\n\ + Supported values are: 8, 10 and 16.\n\ + --totals Show cumulative totals of section sizes.\n\ + --version Display a version identifier and exit.\n\ + -A Equivalent to `--format=sysv'.\n\ + -B Equivalent to `--format=berkeley'.\n\ + -V Equivalent to `--version'.\n\ + -d Equivalent to `--radix=10'.\n\ + -h Same as option --help.\n\ + -o Equivalent to `--radix=8'.\n\ + -t Equivalent to option --totals.\n\ + -x Equivalent to `--radix=16'.\n" + +static void +usage(void) +{ + (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +static void +show_version(void) +{ + (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); + exit(EXIT_SUCCESS); +} diff --git a/contrib/elftoolchain/strings/Makefile b/contrib/elftoolchain/strings/Makefile new file mode 100644 index 000000000000..0bc4cd5d97fe --- /dev/null +++ b/contrib/elftoolchain/strings/Makefile @@ -0,0 +1,11 @@ +# $Id: Makefile 2044 2011-10-23 14:52:59Z jkoshy $ + +TOP= .. + +PROG= strings +WARNS?= 6 +DPADD= ${LIBELFTC} ${LIBELF} +LDADD= -lelftc -lelf + +.include "${TOP}/mk/elftoolchain.prog.mk" + diff --git a/contrib/elftoolchain/strings/strings.1 b/contrib/elftoolchain/strings/strings.1 new file mode 100644 index 000000000000..d6816494e886 --- /dev/null +++ b/contrib/elftoolchain/strings/strings.1 @@ -0,0 +1,162 @@ +.\" Copyright (c) 2007 S.Sam Arun Raj +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: strings.1 2352 2011-12-19 11:21:10Z jkoshy $ +.\" +.Dd December 19, 2011 +.Dt STRINGS 1 +.Os +.Sh NAME +.Nm strings +.Nd "print the strings of printable characters in files" +.Sh SYNOPSIS +.Nm +.Op Fl a | Fl -all +.Op Fl e Ar encoding | Fl -encoding= Ns Ar encoding +.Op Fl f | Fl -print-file-name +.Op Fl h | Fl -help +.Op Fl n Ar number | Fl -bytes= Ns Ar number | Fl Ar number +.Op Fl o +.Op Fl t Ar radix | Fl -radix= Ns Ar radix +.Op Fl v | Fl -version +.Op Ar +.Sh DESCRIPTION +For each +.Ar file +specified, the +.Nm +utility prints contiguous sequences of printable +characters that are at least +.Va n +characters long and are followed by an unprintable character. +The default value of +.Va n +is 4. +By default, the +.Nm +utility only scans the initialized and loaded sections of ELF objects; +for other file types, the entire file is scanned. +The +.Nm +utility is mainly used for determining the contents of non-text files. +.Pp +If no file name is specified as an argument, standard input is read. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a | Fl -all +For ELF objects, scan the entire file for printable strings. +.It Fl e Ar encoding | Fl -encoding= Ns Ar encoding +Select the character encoding to be used while searching for strings. +Valid values for argument +.Ar encoding +are: +.Bl -tag -width indent -compact +.It Ar s +for single 7-bit-byte characters (ASCII, ISO 8859). +.It Ar S +for single 8-bit-byte characters. +.It Ar l +for 16-bit little-endian. +.It Ar b +for 16-bit big-endian. +.It Ar L +for 32-bit little-endian. +.It Ar B +for 32-bit big-endian. +.El +The default is to assume that characters are encoded using a single +7-bit byte. +.It Fl f | Fl -print-file-name +Print the name of the file before each string. +.It Fl h | Fl -help +Print a usage summary and exit. +.It Xo +.Fl n Ar number | +.Fl -bytes= Ns Ar number | +.Fl Ar number +.Xc +Print the contiguous character sequence of at least +.Ar number +characters long, instead of the default of 4 characters. +.It Fl o +Equivalent to specifying +.Fl t Ar o . +.It Fl t Ar radix | Fl -radix= Ns Ar radix +Print the offset from the start of the file before each string +using the specified radix. +Valid values for argument +.Ar radix +are: +.Bl -tag -width indent -compact +.It Ar d +for decimal +.It Ar o +for octal +.It Ar x +for hexadecimal +.El +.It Fl v | Fl -version +Display a version identifier and exit. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +To display strings in +.Pa /bin/ls +use: +.Dl "$ strings /bin/ls" +.Pp +To display strings in all sections of +.Pa /bin/ln +use: +.Dl "$ strings -a /bin/ln" +.Pp +To display strings in all sections of +.Pa /bin/cat +prefixed with the filename and the offset within the file use: +.Dl "$ strings -a -f -t x /bin/cat" +.Sh SEE ALSO +.Xr ar 1 , +.Xr nm 1 , +.Xr objdump 1 , +.Xr ranlib , +.Xr readelf 1 , +.Xr size 1 +.Sh HISTORY +The first FreeBSD +.Nm +utility appeared in +.Fx v3. +It was later discontinued in +.Fx v5 , +when i386-only a.out format was dropped in favor of ELF. +.Sh AUTHORS +.An -nosplit +The +.Nm +utility was re-written by +.An S.Sam Arun Raj Aq samarunraj@gmail.com . +This manual page was written by +.An S.Sam Arun Raj Aq samarunraj@gmail.com . diff --git a/contrib/elftoolchain/strings/strings.c b/contrib/elftoolchain/strings/strings.c new file mode 100644 index 000000000000..c936d5c5374f --- /dev/null +++ b/contrib/elftoolchain/strings/strings.c @@ -0,0 +1,454 @@ +/*- + * Copyright (c) 2007 S.Sam Arun Raj + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: strings.c 2351 2011-12-19 11:20:37Z jkoshy $"); + +enum return_code { + RETURN_OK, + RETURN_NOINPUT, + RETURN_SOFTWARE +}; + +enum radix_style { + RADIX_DECIMAL, + RADIX_HEX, + RADIX_OCTAL +}; + +enum encoding_style { + ENCODING_7BIT, + ENCODING_8BIT, + ENCODING_16BIT_BIG, + ENCODING_16BIT_LITTLE, + ENCODING_32BIT_BIG, + ENCODING_32BIT_LITTLE +}; + +#define PRINTABLE(c) \ + ((c) >= 0 && (c) <= 255 && \ + ((c) == '\t' || isprint((c)) || \ + (encoding == ENCODING_8BIT && (c) > 127))) + + +int encoding_size, entire_file, min_len, show_filename, show_loc; +enum encoding_style encoding; +enum radix_style radix; + +static struct option strings_longopts[] = { + { "all", no_argument, NULL, 'a'}, + { "bytes", required_argument, NULL, 'n'}, + { "encoding", required_argument, NULL, 'e'}, + { "help", no_argument, NULL, 'h'}, + { "print-file-name", no_argument, NULL, 'f'}, + { "radix", required_argument, NULL, 't'}, + { "version", no_argument, NULL, 'v'}, + { NULL, 0, NULL, 0 } +}; + +long getcharacter(void); +int handle_file(const char *); +int handle_elf(const char *, int); +int handle_binary(const char *, int); +int find_strings(const char *, off_t, off_t); +void show_version(void); +void usage(void); + +/* + * strings(1) extracts text(contiguous printable characters) + * from elf and binary files. + */ +int +main(int argc, char **argv) +{ + int ch, rc; + + rc = RETURN_OK; + min_len = 0; + encoding_size = 1; + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "ELF library initialization failed: %s", + elf_errmsg(-1)); + + while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv", + strings_longopts, NULL)) != -1) + switch((char)ch) { + case 'a': + entire_file = 1; + break; + case 'e': + if (*optarg == 's') { + encoding = ENCODING_7BIT; + } else if (*optarg == 'S') { + encoding = ENCODING_8BIT; + } else if (*optarg == 'b') { + encoding = ENCODING_16BIT_BIG; + encoding_size = 2; + } else if (*optarg == 'B') { + encoding = ENCODING_32BIT_BIG; + encoding_size = 4; + } else if (*optarg == 'l') { + encoding = ENCODING_16BIT_LITTLE; + encoding_size = 2; + } else if (*optarg == 'L') { + encoding = ENCODING_32BIT_LITTLE; + encoding_size = 4; + } else + usage(); + /* NOTREACHED */ + break; + case 'f': + show_filename = 1; + break; + case 'n': + min_len = (int)strtoimax(optarg, (char**)NULL, 10); + break; + case 'o': + show_loc = 1; + radix = RADIX_OCTAL; + break; + case 't': + show_loc = 1; + if (*optarg == 'd') + radix = RADIX_DECIMAL; + else if (*optarg == 'o') + radix = RADIX_OCTAL; + else if (*optarg == 'x') + radix = RADIX_HEX; + else + usage(); + /* NOTREACHED */ + break; + case 'v': + case 'V': + show_version(); + /* NOTREACHED */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + min_len *= 10; + min_len += ch - '0'; + break; + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + if (!min_len) + min_len = 4; + if (!*argv) + rc = handle_file("{standard input}"); + else while (*argv) { + rc = handle_file(*argv); + argv++; + } + return (rc); +} + +int +handle_file(const char *name) +{ + int fd, rt; + + if (name == NULL) + return (RETURN_NOINPUT); + if (strcmp("{standard input}", name) != 0) { + if (freopen(name, "rb", stdin) == NULL) { + warnx("'%s': %s", name, strerror(errno)); + return (RETURN_NOINPUT); + } + } else { + return (find_strings(name, (off_t)0, (off_t)0)); + } + + fd = fileno(stdin); + if (fd < 0) + return (RETURN_NOINPUT); + rt = handle_elf(name, fd); + return (rt); +} + +/* + * Files not understood by handle_elf, will be passed off here and will + * treated as a binary file. This would include text file, core dumps ... + */ +int +handle_binary(const char *name, int fd) +{ + struct stat buf; + + memset(&buf, 0, sizeof(struct stat)); + (void) lseek(fd, (off_t)0, SEEK_SET); + if (!fstat(fd, &buf)) + return (find_strings(name, (off_t)0, buf.st_size)); + return (RETURN_SOFTWARE); +} + +/* + * Will analyse a file to see if it ELF, other files including ar(1), + * core dumps are passed off and treated as flat binary files. Unlike + * GNU size in FreeBSD this routine will not treat ELF object from + * different archs as flat binary files(has to overridden using -a). + */ +int +handle_elf(const char *name, int fd) +{ + GElf_Ehdr elfhdr; + GElf_Shdr shdr; + Elf *elf; + Elf_Scn *scn; + int rc; + + rc = RETURN_OK; + /* If entire file is choosen, treat it as a binary file */ + if (entire_file) + return (handle_binary(name, fd)); + + (void) lseek(fd, (off_t)0, SEEK_SET); + elf = elf_begin(fd, ELF_C_READ, NULL); + if (elf_kind(elf) != ELF_K_ELF) { + (void) elf_end(elf); + return (handle_binary(name, fd)); + } + + if (gelf_getehdr(elf, &elfhdr) == NULL) { + (void) elf_end(elf); + warnx("%s: ELF file could not be processed", name); + return (RETURN_SOFTWARE); + } + + if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { + (void) elf_end(elf); + return (handle_binary(name, fd)); + } else { + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) + continue; + if (shdr.sh_type != SHT_NOBITS && + (shdr.sh_flags & SHF_ALLOC) != 0) { + rc = find_strings(name, shdr.sh_offset, + shdr.sh_size); + } + } + } + (void) elf_end(elf); + return (rc); +} + +/* + * Retrieves a character from input stream based on the encoding + * type requested. + */ +long +getcharacter(void) +{ + long rt; + int i; + char buf[4], c; + + rt = EOF; + for(i = 0; i < encoding_size; i++) { + c = getc(stdin); + if (feof(stdin)) + return (EOF); + buf[i] = c; + } + + switch(encoding) { + case ENCODING_7BIT: + case ENCODING_8BIT: + rt = buf[0]; + break; + case ENCODING_16BIT_BIG: + rt = (buf[0] << 8) | buf[1]; + break; + case ENCODING_16BIT_LITTLE: + rt = buf[0] | (buf[1] << 8); + break; + case ENCODING_32BIT_BIG: + rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) | + ((long) buf[2] << 8) | buf[3]; + break; + case ENCODING_32BIT_LITTLE: + rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) | + ((long) buf[3] << 24); + break; + } + return (rt); +} + +/* + * Input stream stdin is read until the end of file is reached or until + * the section size is reached in case of ELF files. Contiguous + * characters of >= min_size(default 4) will be displayed. + */ +int +find_strings(const char *name, off_t offset, off_t size) +{ + off_t cur_off, start_off; + char *obuf; + long c; + int i; + + if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) { + (void) fprintf(stderr, "Unable to allocate memory: %s\n", + strerror(errno)); + return (RETURN_SOFTWARE); + } + + (void) fseeko(stdin, offset, SEEK_SET); + cur_off = offset; + start_off = 0; + while(1) { + if ((offset + size) && (cur_off >= offset + size)) + break; + start_off = cur_off; + memset(obuf, 0, min_len+1); + for(i = 0; i < min_len; i++) { + c = getcharacter(); + if (c == EOF && feof(stdin)) + goto _exit1; + if (PRINTABLE(c)) { + obuf[i] = c; + obuf[i+1] = 0; + cur_off += encoding_size; + } else { + if (encoding == ENCODING_8BIT && + (uint8_t)c > 127) { + obuf[i] = c; + obuf[i+1] = 0; + cur_off += encoding_size; + continue; + } + cur_off += encoding_size; + break; + } + } + + if (i >= min_len && ((cur_off <= offset + size) || + !(offset + size))) { + if (show_filename) + printf ("%s: ", name); + if (show_loc) { + switch(radix) { + case RADIX_DECIMAL: + (void) printf("%7ju ", + (uintmax_t)start_off); + break; + case RADIX_HEX: + (void) printf("%7jx ", + (uintmax_t)start_off); + break; + case RADIX_OCTAL: + (void) printf("%7jo ", + (uintmax_t)start_off); + break; + } + } + printf("%s", obuf); + + while(1) { + if ((offset + size) && + (cur_off >= offset + size)) + break; + c = getcharacter(); + cur_off += encoding_size; + if (encoding == ENCODING_8BIT && + (uint8_t)c > 127) { + putchar(c); + continue; + } + if (!PRINTABLE(c) || c == EOF) + break; + putchar(c); + } + putchar('\n'); + } + } +_exit1: + free(obuf); + return (RETURN_OK); +} + +#define USAGE_MESSAGE "\ +Usage: %s [options] [file...]\n\ + Print contiguous sequences of printable characters.\n\n\ + Options:\n\ + -a | --all Scan the entire file for strings.\n\ + -e ENC | --encoding=ENC Select the character encoding to use.\n\ + -f | --print-file-name Print the file name before each string.\n\ + -h | --help Print a help message and exit.\n\ + -n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\ + -o Print offsets in octal.\n\ + -t R | --radix=R Print offsets using the radix named by 'R'.\n\ + -v | --version Print a version identifier and exit.\n" + +void +usage(void) +{ + (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +void +show_version(void) +{ + (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); + exit(EXIT_SUCCESS); +} diff --git a/contrib/libucl/COPYING b/contrib/libucl/COPYING new file mode 100644 index 000000000000..33048e1b8b97 --- /dev/null +++ b/contrib/libucl/COPYING @@ -0,0 +1,23 @@ +Copyright (c) 2013-2014, Vsevolod Stakhov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/libucl/ChangeLog.md b/contrib/libucl/ChangeLog.md index 09c331f4c6d1..0df5e072222e 100644 --- a/contrib/libucl/ChangeLog.md +++ b/contrib/libucl/ChangeLog.md @@ -4,3 +4,19 @@ - Streamline emitter has been added, so it is now possible to output partial `ucl` objects - Emitter now is more flexible due to emitter_context structure + +### 0.5.1 +- Fixed number of bugs and memory leaks + +### 0.5.2 + +- Allow userdata objects to be emitted and destructed +- Use userdata objects to store lua function references + +### Libucl 0.6 + +- Reworked macro interface + +### Libucl 0.6.1 + +- Various utilities fixes diff --git a/contrib/libucl/Makefile.am b/contrib/libucl/Makefile.am index 558c5a5b546a..ece5b97df488 100644 --- a/contrib/libucl/Makefile.am +++ b/contrib/libucl/Makefile.am @@ -4,4 +4,8 @@ EXTRA_DIST = uthash README.md pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libucl.pc -SUBDIRS = src tests utils doc +if LUA_SUB + LUA_SUBDIR = lua +endif + +SUBDIRS = src tests utils doc $(LUA_SUBDIR) \ No newline at end of file diff --git a/contrib/libucl/Makefile.w32 b/contrib/libucl/Makefile.w32 index 62ff14a3a296..0e61274ff59c 100644 --- a/contrib/libucl/Makefile.w32 +++ b/contrib/libucl/Makefile.w32 @@ -33,6 +33,7 @@ OBJECTS = $(OBJDIR)/ucl_hash.o \ $(OBJDIR)/ucl_util.o \ $(OBJDIR)/ucl_parser.o \ $(OBJDIR)/ucl_emitter.o \ + $(OBJDIR)/ucl_emitter_utils.o \ $(OBJDIR)/ucl_schema.o \ $(OBJDIR)/xxhash.o @@ -51,6 +52,8 @@ $(OBJDIR)/ucl_parser.o: $(SRCDIR)/ucl_parser.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_parser.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_parser.c $(OBJDIR)/ucl_emitter.o: $(SRCDIR)/ucl_emitter.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_emitter.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter.c +$(OBJDIR)/ucl_emitter_utils.o: $(SRCDIR)/ucl_emitter_utils.c $(HDEPS) + $(CC) -o $(OBJDIR)/ucl_emitter_utils.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter_utils.c $(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS) $(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c $(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS) @@ -61,7 +64,7 @@ $(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS) clean: $(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate $(RMDIR) $(OBJDIR) - + # Utils chargen: utils/chargen.c $(OBJDIR)/$(SONAME) @@ -75,7 +78,7 @@ test: $(OBJDIR) $(OBJDIR)/$(SONAME) $(OBJDIR)/test_basic $(OBJDIR)/test_speed $( run-test: test TEST_DIR=$(TESTDIR) $(TESTDIR)/run_tests.sh $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate - + $(OBJDIR)/test_basic: $(TESTDIR)/test_basic.c $(OBJDIR)/$(SONAME) $(CC) -o $(OBJDIR)/test_basic $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_basic.c $(LD_UCL_FLAGS) $(OBJDIR)/test_speed: $(TESTDIR)/test_speed.c $(OBJDIR)/$(SONAME) diff --git a/contrib/libucl/README.md b/contrib/libucl/README.md index b6353d10ae27..235cfb6595df 100644 --- a/contrib/libucl/README.md +++ b/contrib/libucl/README.md @@ -223,15 +223,57 @@ UCL supports external macros both multiline and single line ones: .... }; ``` -There are two internal macros provided by UCL: -* `include` - read a file `/path/to/file` or an url `http://example.com/file` and include it to the current place of -UCL configuration; -* `try\_include` - try to read a file or url and include it but do not create a fatal error if a file or url is not accessible; -* `includes` - read a file or an url like the previous macro, but fetch and check the signature file (which is obtained -by `.sig` suffix appending). +Moreover, each macro can accept an optional list of arguments in braces. These +arguments themselves are the UCL object that is parsed and passed to a macro as +options: -Public keys which are used for the last command are specified by the concrete UCL user. +```nginx +.macro(param=value) "something"; +.macro(param={key=value}) "something"; +.macro(.include "params.conf") "something"; +.macro(#this is multiline macro +param = [value1, value2]) "something"; +.macro(key="()") "something"; +``` + +UCL also provide a convenient `include` macro to load content from another files +to the current UCL object. This macro accepts either path to file: + +```nginx +.include "/full/path.conf" +.include "./relative/path.conf" +.include "${CURDIR}/path.conf" +``` + +or URL (if ucl is built with url support provided by either `libcurl` or `libfetch`): + + .include "http://example.com/file.conf" + +`.include` macro supports a set of options: + +* `try` (default: **false**) - if this option is `true` than UCL treats errors on loading of +this file as non-fatal. For example, such a file can be absent but it won't stop the parsing +of the top-level document. +* `sign` (default: **false**) - if this option is `true` UCL loads and checks the signature for +a file from path named `.sig`. Trusted public keys should be provided for UCL API after +parser is created but before any configurations are parsed. +* `glob` (default: **false**) - if this option is `true` UCL treats the filename as GLOB pattern and load +all files that matches the specified pattern (normally the format of patterns is defined in `glob` manual page +for your operating system). This option is meaningless for URL includes. +* `url` (default: **true**) - allow URL includes. +* `priority` (default: 0) - specify priority for the include (see below). + +Priorities are used by UCL parser to manage the policy of objects rewriting during including other files +as following: + +* If we have two objects with the same priority then we form an implicit array +* If a new object has bigger priority then we overwrite an old one +* If a new object has lower priority then we ignore it + +By default, the priority of top-level object is set to zero (lowest priority). Currently, +you can define up to 16 priorities (from 0 to 15). Includes with bigger priorities will +rewrite keys from the objects with lower priorities as specified by the policy. ### Variables support @@ -317,7 +359,7 @@ ucl: emitted compact json in 0.0991 seconds ucl: emitted yaml in 0.1354 seconds ``` -You can do your own benchmarks by running `make test` in libucl top directory. +You can do your own benchmarks by running `make check` in libucl top directory. ## Conclusion diff --git a/contrib/libucl/cmake/CMakeLists.txt b/contrib/libucl/cmake/CMakeLists.txt index 4551966135ea..3c57db53784a 100644 --- a/contrib/libucl/cmake/CMakeLists.txt +++ b/contrib/libucl/cmake/CMakeLists.txt @@ -1,8 +1,8 @@ PROJECT(libucl C) SET(LIBUCL_VERSION_MAJOR 0) -SET(LIBUCL_VERSION_MINOR 2) -SET(LIBUCL_VERSION_PATCH 9) +SET(LIBUCL_VERSION_MINOR 5) +SET(LIBUCL_VERSION_PATCH 0) SET(LIBUCL_VERSION "${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}") @@ -86,6 +86,8 @@ INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../uthash") SET(UCLSRC ../src/ucl_util.c ../src/ucl_parser.c ../src/ucl_emitter.c + ../src/ucl_emitter_streamline.c + ../src/ucl_emitter_utils.c ../src/ucl_hash.c ../src/ucl_schema.c ../src/xxhash.c) @@ -98,6 +100,18 @@ ENDIF (BUILD_SHARED_LIBS) ADD_LIBRARY(ucl ${LIB_TYPE} ${UCLSRC}) SET_TARGET_PROPERTIES(ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR}) +IF(WITH_LUA) + SET(UCL_LUA_SRC ../lua/lua_ucl.c) + ADD_LIBRARY(lua-ucl ${LIB_TYPE} ${UCL_LUA_SRC}) + IF(ENABLE_LUAJIT MATCHES "ON") + TARGET_LINK_LIBRARIES(lua-ucl "${LUAJIT_LIBRARY}") + ELSE(ENABLE_LUAJIT MATCHES "ON") + TARGET_LINK_LIBRARIES(lua-ucl "${LUA_LIBRARY}") + ENDIF(ENABLE_LUAJIT MATCHES "ON") + TARGET_LINK_LIBRARIES(lua-ucl ucl) + SET_TARGET_PROPERTIES(lua-ucl PROPERTIES VERSION ${LIBUCL_VERSION} SOVERSION ${LIBUCL_VERSION_MAJOR}) +ENDIF(WITH_LUA) + IF(HAVE_FETCH_H) TARGET_LINK_LIBRARIES(ucl fetch) ELSE(HAVE_FETCH_H) diff --git a/contrib/libucl/configure.ac b/contrib/libucl/configure.ac index 2d612f6236e8..32db73ad0fdd 100644 --- a/contrib/libucl/configure.ac +++ b/contrib/libucl/configure.ac @@ -1,12 +1,13 @@ m4_define([maj_ver], [0]) -m4_define([med_ver], [5]) -m4_define([min_ver], [0]) -m4_define([so_version], [2:0:0]) +m4_define([med_ver], [6]) +m4_define([min_ver], [1]) +m4_define([so_version], [3:0:1]) m4_define([ucl_version], [maj_ver.med_ver.min_ver]) AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl]) AC_CONFIG_SRCDIR([configure.ac]) -AM_INIT_AUTOMAKE([1.11 foreign silent-rules -Wall -Wportability no-dist-gzip dist-xz]) +AM_INIT_AUTOMAKE([1.11 foreign -Wall -Wportability no-dist-gzip dist-xz]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) UCL_VERSION=ucl_version SO_VERSION=so_version @@ -57,6 +58,9 @@ AC_ARG_ENABLE([regex], AS_HELP_STRING([--enable-regex], AC_ARG_ENABLE([signatures], AS_HELP_STRING([--enable-signatures], [Enable signatures check (requires openssl) @<:@default=no@:>@]), [], [enable_signatures=no]) +AC_ARG_ENABLE([lua], AS_HELP_STRING([--enable-lua], + [Enable lua API build (requires lua libraries and headers) @<:@default=no@:>@]), [], + [enable_lua=no]) AC_ARG_ENABLE([utils], AS_HELP_STRING([--enable-utils], [Build and install utils @<:@default=no@:>@]), [case "${enableval}" in @@ -99,6 +103,21 @@ AS_IF([test "x$enable_regex" = "xyes"], [ ]) AC_SUBST(LIBREGEX_LIB) +AS_IF([test "x$enable_lua" = "xyes"], [ + AX_PROG_LUA([5.1], [], [ + AX_LUA_HEADERS([ + AX_LUA_LIBS([ + AC_DEFINE(HAVE_LUA, 1, [Define to 1 for lua support.]) + with_lua="yes" + ], [AC_MSG_ERROR([unable to find the lua libraries]) + ]) + ], [AC_MSG_ERROR([unable to find the lua header files]) + ]) + ], [AC_MSG_ERROR([unable to find the lua interpreter])]) +], [with_lua="no"]) + +AM_CONDITIONAL([LUA_SUB], [test "$with_lua" = "yes"]) + AS_IF([test "x$enable_urls" = "xyes"], [ AC_CHECK_HEADER([fetch.h], [ AC_DEFINE(HAVE_FETCH_H, 1, [Define to 1 if you have the header file.]) @@ -155,9 +174,11 @@ AC_LINK_IFELSE([ AC_CONFIG_FILES(Makefile \ src/Makefile \ + lua/Makefile tests/Makefile \ utils/Makefile \ doc/Makefile \ + lua/libucl.rockspec \ libucl.pc) AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) AC_OUTPUT diff --git a/contrib/libucl/doc/lua_api.md b/contrib/libucl/doc/lua_api.md new file mode 100644 index 000000000000..a53353b3c57e --- /dev/null +++ b/contrib/libucl/doc/lua_api.md @@ -0,0 +1,194 @@ +## Module `ucl` + +This lua module allows to parse objects from strings and to store data into +ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects. + +Example: + +~~~lua +local ucl = require("ucl") + +local parser = ucl.parser() +local res,err = parser:parse_string('{key=value}') + +if not res then + print('parser error: ' .. err) +else + local obj = parser:get_object() + local got = ucl.to_format(obj, 'json') +endif + +local table = { + str = 'value', + num = 100500, + null = ucl.null, + func = function () + return 'huh' + end + + +print(ucl.to_format(table, 'ucl')) +-- Output: +--[[ +num = 100500; +str = "value"; +null = null; +func = "huh"; +--]] +~~~ + +###Brief content: + +**Functions**: + +> [`ucl_object_push_lua(L, obj, allow_array)`](#function-ucl_object_push_lual-obj-allow_array) + +> [`ucl.to_format(var, format)`](#function-uclto_formatvar-format) + + + +**Methods**: + +> [`parser:parse_file(name)`](#method-parserparse_filename) + +> [`parser:parse_string(input)`](#method-parserparse_stringinput) + +> [`parser:get_object()`](#method-parserget_object) + + +## Functions + +The module `ucl` defines the following functions. + +### Function `ucl_object_push_lua(L, obj, allow_array)` + +This is a `C` function to push `UCL` object as lua variable. This function +converts `obj` to lua representation using the following conversions: + +- *scalar* values are directly presented by lua objects +- *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`, +this can be used to pass functions from lua to c and vice-versa +- *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations +- *objects* are converted to lua tables with string indicies + +**Parameters:** + +- `L {lua_State}`: lua state pointer +- `obj {ucl_object_t}`: object to push +- `allow_array {bool}`: expand implicit arrays (should be true for all but partial arrays) + +**Returns:** + +- `{int}`: `1` if an object is pushed to lua + +Back to [module description](#module-ucl). + +### Function `ucl.to_format(var, format)` + +Converts lua variable `var` to the specified `format`. Formats supported are: + +- `json` - fine printed json +- `json-compact` - compacted json +- `config` - fine printed configuration +- `ucl` - same as `config` +- `yaml` - embedded yaml + +If `var` contains function, they are called during output formatting and if +they return string value, then this value is used for ouptut. + +**Parameters:** + +- `var {variant}`: any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output) +- `format {string}`: any available format + +**Returns:** + +- `{string}`: string representation of `var` in the specific `format`. + +Example: + +~~~lua +local table = { + str = 'value', + num = 100500, + null = ucl.null, + func = function () + return 'huh' + end + + +print(ucl.to_format(table, 'ucl')) +-- Output: +--[[ +num = 100500; +str = "value"; +null = null; +func = "huh"; +--]] +~~~ + +Back to [module description](#module-ucl). + + +## Methods + +The module `ucl` defines the following methods. + +### Method `parser:parse_file(name)` + +Parse UCL object from file. + +**Parameters:** + +- `name {string}`: filename to parse + +**Returns:** + +- `{bool[, string]}`: if res is `true` then file has been parsed successfully, otherwise an error string is also returned + +Example: + +~~~lua +local parser = ucl.parser() +local res,err = parser:parse_file('/some/file.conf') + +if not res then + print('parser error: ' .. err) +else + -- Do something with object +end +~~~ + +Back to [module description](#module-ucl). + +### Method `parser:parse_string(input)` + +Parse UCL object from file. + +**Parameters:** + +- `input {string}`: string to parse + +**Returns:** + +- `{bool[, string]}`: if res is `true` then file has been parsed successfully, otherwise an error string is also returned + +Back to [module description](#module-ucl). + +### Method `parser:get_object()` + +Get top object from parser and export it to lua representation. + +**Parameters:** + + nothing + +**Returns:** + +- `{variant or nil}`: ucl object as lua native variable + +Back to [module description](#module-ucl). + + +Back to [top](#). + diff --git a/contrib/libucl/include/lua_ucl.h b/contrib/libucl/include/lua_ucl.h new file mode 100644 index 000000000000..38e74d3f619d --- /dev/null +++ b/contrib/libucl/include/lua_ucl.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2014, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef LUA_UCL_H_ +#define LUA_UCL_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "ucl.h" + +/** + * Closure structure for lua function storing inside UCL + */ +struct ucl_lua_funcdata { + lua_State *L; + int idx; + char *ret; +}; + +/** + * Initialize lua UCL API + */ +UCL_EXTERN int luaopen_ucl (lua_State *L); + +/** + * Import UCL object from lua state + * @param L lua state + * @param idx index of object at the lua stack to convert to UCL + * @return new UCL object or NULL, the caller should unref object after using + */ +UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx); + +/** + * Push an object to lua + * @param L lua state + * @param obj object to push + * @param allow_array traverse over implicit arrays + */ +UCL_EXTERN int ucl_object_push_lua (lua_State *L, + const ucl_object_t *obj, bool allow_array); + +UCL_EXTERN struct ucl_lua_funcdata* ucl_object_toclosure ( + const ucl_object_t *obj); + +#endif /* LUA_UCL_H_ */ diff --git a/contrib/libucl/include/ucl.h b/contrib/libucl/include/ucl.h index b40f11322508..1aac6a25332c 100644 --- a/contrib/libucl/include/ucl.h +++ b/contrib/libucl/include/ucl.h @@ -147,7 +147,8 @@ typedef enum ucl_emitter { typedef enum ucl_parser_flags { UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ UCL_PARSER_ZEROCOPY = 0x2, /**< Parse input in zero-copy mode if possible */ - UCL_PARSER_NO_TIME = 0x4 /**< Do not parse time and treat time values as strings */ + UCL_PARSER_NO_TIME = 0x4, /**< Do not parse time and treat time values as strings */ + UCL_PARSER_NO_IMPLICIT_ARRAYS = 0x8 /** Create explicit arrays instead of implicit ones */ } ucl_parser_flags_t; /** @@ -171,9 +172,12 @@ typedef enum ucl_string_flags { * Basic flags for an object */ typedef enum ucl_object_flags { - UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ - UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ - UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ + UCL_OBJECT_ALLOCATED_KEY = 0x1, /**< An object has key allocated internally */ + UCL_OBJECT_ALLOCATED_VALUE = 0x2, /**< An object has a string value allocated internally */ + UCL_OBJECT_NEED_KEY_ESCAPE = 0x4, /**< The key of an object need to be escaped on output */ + UCL_OBJECT_EPHEMERAL = 0x8, /**< Temporary object that does not need to be freed really */ + UCL_OBJECT_MULTILINE = 0x10, /**< String should be displayed as multiline string */ + UCL_OBJECT_MULTIVALUE = 0x20 /**< Object is a key with multiple values */ } ucl_object_flags_t; /** @@ -195,14 +199,21 @@ typedef struct ucl_object_s { const char *key; /**< Key of an object */ struct ucl_object_s *next; /**< Array handle */ struct ucl_object_s *prev; /**< Array handle */ - unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ - unsigned keylen; /**< Lenght of a key */ - unsigned len; /**< Size of an object */ - enum ucl_type type; /**< Real type */ - uint16_t ref; /**< Reference count */ + uint32_t keylen; /**< Lenght of a key */ + uint32_t len; /**< Size of an object */ + uint32_t ref; /**< Reference count */ uint16_t flags; /**< Object flags */ + uint16_t type; /**< Real type */ + unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ } ucl_object_t; +/** + * Destructor type for userdata objects + * @param ud user specified data pointer + */ +typedef void (*ucl_userdata_dtor)(void *ud); +typedef const char* (*ucl_userdata_emitter)(void *ud); + /** @} */ /** @@ -238,6 +249,31 @@ UCL_EXTERN ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; */ UCL_EXTERN ucl_object_t* ucl_object_typed_new (ucl_type_t type) UCL_WARN_UNUSED_RESULT; +/** + * Create new object with type and priority specified + * @param type type of a new object + * @param priority priority of an object + * @return new object + */ +UCL_EXTERN ucl_object_t* ucl_object_new_full (ucl_type_t type, unsigned priority) + UCL_WARN_UNUSED_RESULT; + +/** + * Create new object with userdata dtor + * @param dtor destructor function + * @return new object + */ +UCL_EXTERN ucl_object_t* ucl_object_new_userdata (ucl_userdata_dtor dtor, + ucl_userdata_emitter emitter) UCL_WARN_UNUSED_RESULT; + +/** + * Perform deep copy of an object copying everything + * @param other object to copy + * @return new object with refcount equal to 1 + */ +UCL_EXTERN ucl_object_t * ucl_object_copy (const ucl_object_t *other) + UCL_WARN_UNUSED_RESULT; + /** * Return the type of an object * @return the object type @@ -293,7 +329,7 @@ UCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv) UCL_WARN_UNUSED_RESULT; /** * Insert a object 'elt' to the hash 'top' and associate it with key 'key' - * @param top destination object (will be created automatically if top is NULL) + * @param top destination object (must be of type UCL_OBJECT) * @param elt element to insert (must NOT be NULL) * @param key key to associate with this object (either const or preallocated) * @param keylen length of the key (or 0 for NULL terminated keys) @@ -306,7 +342,7 @@ UCL_EXTERN bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, /** * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, * if no object has been found this function works like ucl_object_insert_key() - * @param top destination object (will be created automatically if top is NULL) + * @param top destination object (must be of type UCL_OBJECT) * @param elt element to insert (must NOT be NULL) * @param key key to associate with this object (either const or preallocated) * @param keylen length of the key (or 0 for NULL terminated keys) @@ -316,6 +352,15 @@ UCL_EXTERN bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, UCL_EXTERN bool ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key); +/** + * Merge the keys from one object to another object. Overwrite on conflict + * @param top destination object (must be of type UCL_OBJECT) + * @param elt element to insert (must be of type UCL_OBJECT) + * @param copy copy rather than reference the elements + * @return true if all keys have been merged + */ +UCL_EXTERN bool ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy); + /** * Delete a object associated with key 'key', old object will be unrefered, * @param top object @@ -335,8 +380,9 @@ UCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, /** - * Delete key from `top` object returning the object deleted. This object is not - * released + * Removes `key` from `top` object, returning the object that was removed. This + * object is not released, caller must unref the returned object when it is no + * longer needed. * @param top object * @param key key to remove * @param keylen length of the key (or 0 for NULL terminated keys) @@ -346,8 +392,9 @@ UCL_EXTERN ucl_object_t* ucl_object_pop_keyl (ucl_object_t *top, const char *key size_t keylen) UCL_WARN_UNUSED_RESULT; /** - * Delete key from `top` object returning the object deleted. This object is not - * released + * Removes `key` from `top` object returning the object that was removed. This + * object is not released, caller must unref the returned object when it is no + * longer needed. * @param top object * @param key key to remove * @return removed object or NULL if object has not been found @@ -356,9 +403,9 @@ UCL_EXTERN ucl_object_t* ucl_object_pop_key (ucl_object_t *top, const char *key) UCL_WARN_UNUSED_RESULT; /** - * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, - * try to merge its content - * @param top destination object (will be created automatically if top is NULL) + * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if + * the specified key exist, try to merge its content + * @param top destination object (must be of type UCL_OBJECT) * @param elt element to insert (must NOT be NULL) * @param key key to associate with this object (either const or preallocated) * @param keylen length of the key (or 0 for NULL terminated keys) @@ -369,8 +416,8 @@ UCL_EXTERN bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *e const char *key, size_t keylen, bool copy_key); /** - * Append an element to the front of array object - * @param top destination object (will be created automatically if top is NULL) + * Append an element to the end of array object + * @param top destination object (must NOT be NULL) * @param elt element to append (must NOT be NULL) * @return true if value has been inserted */ @@ -379,7 +426,7 @@ UCL_EXTERN bool ucl_array_append (ucl_object_t *top, /** * Append an element to the start of array object - * @param top destination object (will be created automatically if top is NULL) + * @param top destination object (must NOT be NULL) * @param elt element to append (must NOT be NULL) * @return true if value has been inserted */ @@ -387,8 +434,19 @@ UCL_EXTERN bool ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt); /** - * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not - * needed. + * Merge all elements of second array into the first array + * @param top destination array (must be of type UCL_ARRAY) + * @param elt array to copy elements from (must be of type UCL_ARRAY) + * @param copy copy elements instead of referencing them + * @return true if arrays were merged + */ +UCL_EXTERN bool ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, + bool copy); + +/** + * Removes an element `elt` from the array `top`, returning the object that was + * removed. This object is not released, caller must unref the returned object + * when it is no longer needed. * @param top array ucl object * @param elt element to remove * @return removed element or NULL if `top` is NULL or not an array @@ -411,35 +469,50 @@ UCL_EXTERN const ucl_object_t* ucl_array_head (const ucl_object_t *top); UCL_EXTERN const ucl_object_t* ucl_array_tail (const ucl_object_t *top); /** - * Removes the last element from the array `top`. Caller must unref the returned object when it is not - * needed. + * Removes the last element from the array `top`, returning the object that was + * removed. This object is not released, caller must unref the returned object + * when it is no longer needed. * @param top array ucl object * @return removed element or NULL if `top` is NULL or not an array */ UCL_EXTERN ucl_object_t* ucl_array_pop_last (ucl_object_t *top); /** - * Return object identified by an index of the array `top` - * @param obj object to get a key from (must be of type UCL_ARRAY) - * @param index index to return - * @return object at the specified index or NULL if index is not found - */ -UCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top, - unsigned int index); - -/** - * Removes the first element from the array `top`. Caller must unref the returned object when it is not - * needed. + * Removes the first element from the array `top`, returning the object that was + * removed. This object is not released, caller must unref the returned object + * when it is no longer needed. * @param top array ucl object * @return removed element or NULL if `top` is NULL or not an array */ UCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top); +/** + * Return object identified by index of the array `top` + * @param top object to get a key from (must be of type UCL_ARRAY) + * @param index array index to return + * @return object at the specified index or NULL if index is not found + */ +UCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top, + unsigned int index); + +/** + * Replace an element in an array with a different element, returning the object + * that was replaced. This object is not released, caller must unref the + * returned object when it is no longer needed. + * @param top destination object (must be of type UCL_ARRAY) + * @param elt element to append (must NOT be NULL) + * @param index array index in destination to overwrite with elt + * @return object that was replaced or NULL if index is not found + */ +ucl_object_t * +ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt, + unsigned int index); + /** * Append a element to another element forming an implicit array * @param head head to append (may be NULL) * @param elt new element - * @return true if element has been inserted + * @return the new implicit array */ UCL_EXTERN ucl_object_t * ucl_elt_append (ucl_object_t *head, ucl_object_t *elt); @@ -533,7 +606,7 @@ UCL_EXTERN const char* ucl_object_tolstring (const ucl_object_t *obj, size_t *tl * Return object identified by a key in the specified object * @param obj object to get a key from (must be of type UCL_OBJECT) * @param key key to search - * @return object matched the specified key or NULL if key is not found + * @return object matching the specified key or NULL if key was not found */ UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj, const char *key); @@ -543,7 +616,7 @@ UCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj, * @param obj object to get a key from (must be of type UCL_OBJECT) * @param key key to search * @param klen length of a key - * @return object matched the specified key or NULL if key is not found + * @return object matching the specified key or NULL if key was not found */ UCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen); @@ -575,6 +648,7 @@ UCL_EXTERN const char* ucl_object_keyl (const ucl_object_t *obj, size_t *len); /** * Increase reference count for an object * @param obj object to ref + * @return the referenced object */ UCL_EXTERN ucl_object_t* ucl_object_ref (const ucl_object_t *obj); @@ -611,6 +685,21 @@ UCL_EXTERN int ucl_object_compare (const ucl_object_t *o1, UCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar, int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2)); +/** + * Get the priority for specific UCL object + * @param obj any ucl object + * @return priority of an object + */ +UCL_EXTERN unsigned int ucl_object_get_priority (const ucl_object_t *obj); + +/** + * Set explicit priority of an object. + * @param obj any ucl object + * @param priority new priroity value (only 4 least significant bits are considred) + */ +UCL_EXTERN void ucl_object_set_priority (ucl_object_t *obj, + unsigned int priority); + /** * Opaque iterator object */ @@ -640,11 +729,14 @@ UCL_EXTERN const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj, * Macro handler for a parser * @param data the content of macro * @param len the length of content + * @param arguments arguments object * @param ud opaque user data * @param err error pointer * @return true if macro has been parsed */ -typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); +typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, + const ucl_object_t *arguments, + void* ud); /* Opaque parser */ struct ucl_parser; @@ -702,12 +794,23 @@ UCL_EXTERN void ucl_parser_set_variables_handler (struct ucl_parser *parser, * @param parser parser structure * @param data the pointer to the beginning of a chunk * @param len the length of a chunk - * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ UCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); +/** + * Load new chunk to a parser with the specified priority + * @param parser parser structure + * @param data the pointer to the beginning of a chunk + * @param len the length of a chunk + * @param priority the desired priority of a chunk (only 4 least significant bits + * are considered for this parameter) + * @return true if chunk has been added and false in case of error + */ +UCL_EXTERN bool ucl_parser_add_chunk_priority (struct ucl_parser *parser, + const unsigned char *data, size_t len, unsigned priority); + /** * Load ucl object from a string * @param parser parser structure @@ -835,7 +938,7 @@ struct ucl_emitter_context { /** A set of output operations */ const struct ucl_emitter_operations *ops; /** Current amount of indent tabs */ - unsigned int ident; + unsigned int indent; /** Top level object */ const ucl_object_t *top; /** The rest of context */ diff --git a/contrib/libucl/libucl.pc.in b/contrib/libucl/libucl.pc.in index 975462d21fdc..3433fa9d8b1c 100644 --- a/contrib/libucl/libucl.pc.in +++ b/contrib/libucl/libucl.pc.in @@ -7,5 +7,5 @@ Name: LibUCL Description: Universal configuration library Version: @UCL_VERSION@ Libs: -L${libdir} -lucl -Libs.private: @LIBS_EXTRA@ +Libs.private: @LIBS_EXTRA@ @LUA_LIB@ Cflags: -I${includedir}/ diff --git a/contrib/libucl/lua/Makefile.am b/contrib/libucl/lua/Makefile.am new file mode 100644 index 000000000000..95beafbfc94e --- /dev/null +++ b/contrib/libucl/lua/Makefile.am @@ -0,0 +1,26 @@ +ucl_common_cflags= -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/uthash \ + -Wall -W -Wno-unused-parameter -Wno-pointer-sign +luaexec_LTLIBRARIES= ucl.la +ucl_la_SOURCES= lua_ucl.c +ucl_la_CFLAGS= $(ucl_common_cflags) \ + @LUA_INCLUDE@ +ucl_la_LDFLAGS = -module -export-dynamic -avoid-version +ucl_la_LIBADD= $(top_srcdir)/src/libucl.la \ + @LIBFETCH_LIBS@ \ + @LIBCRYPTO_LIB@ \ + @LIBREGEX_LIB@ \ + @CURL_LIBS@ \ + @LUA_LIB@ + +include_HEADERS= $(top_srcdir)/include/lua_ucl.h + +ROCKSPEC = $(PACKAGE)-$(VERSION)-1.rockspec +EXTRA_DIST = $(PACKAGE).rockspec.in \ + test.lua +DISTCLEANFILES = $(PACKAGE).rockspec + +$(ROCKSPEC): $(PACKAGE).rockspec dist + sed -e 's/@MD5@/'`$(MD5SUM) $(distdir).tar.gz | \ + cut -d " " -f 1`'/g' < $(PACKAGE).rockspec > $@ \ No newline at end of file diff --git a/contrib/libucl/lua/libucl.rockspec.in b/contrib/libucl/lua/libucl.rockspec.in new file mode 100644 index 000000000000..52f39176a7bd --- /dev/null +++ b/contrib/libucl/lua/libucl.rockspec.in @@ -0,0 +1,26 @@ +package="@PACKAGE@" +version="@VERSION@-1" +source = { + url = "https://github.com/downloads/vstakhov/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz", + md5 = "@MD5@", + dir = "@PACKAGE@-@VERSION@" +} +description = { + summary = "UCL - json like configuration language", + detailed = [[ + UCL is heavily infused by nginx configuration as the example + of a convenient configuration system. + However, UCL is fully compatible with JSON format and is able + to parse json files. + ]], + homepage = "http://github.com/vstakhov/@PACKAGE@/", + license = "" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "command", + build_command = "LUA=$(LUA) CPPFLAGS=-I$(LUA_INCDIR) ./configure --prefix=$(PREFIX) --libdir=$(LIBDIR) --datadir=$(LUADIR) && make clean && make", + install_command = "make install" +} diff --git a/contrib/libucl/lua/lua_ucl.c b/contrib/libucl/lua/lua_ucl.c new file mode 100644 index 000000000000..682b0b559fd3 --- /dev/null +++ b/contrib/libucl/lua/lua_ucl.c @@ -0,0 +1,820 @@ +/* Copyright (c) 2014, Vsevolod Stakhov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file lua ucl bindings + */ + +#include "ucl.h" +#include "ucl_internal.h" +#include "lua_ucl.h" +#include + +/*** + * @module ucl + * This lua module allows to parse objects from strings and to store data into + * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects. + * @example +local ucl = require("ucl") + +local parser = ucl.parser() +local res,err = parser:parse_string('{key=value}') + +if not res then + print('parser error: ' .. err) +else + local obj = parser:get_object() + local got = ucl.to_format(obj, 'json') +endif + +local table = { + str = 'value', + num = 100500, + null = ucl.null, + func = function () + return 'huh' + end +} + +print(ucl.to_format(table, 'ucl')) +-- Output: +--[[ +num = 100500; +str = "value"; +null = null; +func = "huh"; +--]] + */ + +#define PARSER_META "ucl.parser.meta" +#define EMITTER_META "ucl.emitter.meta" +#define NULL_META "null.emitter.meta" + +static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj); +static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, bool allow_array); +static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx); +static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx); + +static void *ucl_null; + +/** + * Push a single element of an object to lua + * @param L + * @param key + * @param obj + */ +static void +ucl_object_lua_push_element (lua_State *L, const char *key, + const ucl_object_t *obj) +{ + lua_pushstring (L, key); + ucl_object_push_lua (L, obj, true); + lua_settable (L, -3); +} + +static void +lua_ucl_userdata_dtor (void *ud) +{ + struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; + + luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx); + if (fd->ret != NULL) { + free (fd->ret); + } + free (fd); +} + +static const char * +lua_ucl_userdata_emitter (void *ud) +{ + struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud; + const char *out = ""; + + lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx); + + lua_pcall (fd->L, 0, 1, 0); + out = lua_tostring (fd->L, -1); + + if (out != NULL) { + /* We need to store temporary string in a more appropriate place */ + if (fd->ret) { + free (fd->ret); + } + fd->ret = strdup (out); + } + + lua_settop (fd->L, 0); + + return fd->ret; +} + +/** + * Push a single object to lua + * @param L + * @param obj + * @return + */ +static int +ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj, + bool allow_array) +{ + const ucl_object_t *cur; + ucl_object_iter_t it = NULL; + int nelt = 0; + + if (allow_array && obj->next != NULL) { + /* Actually we need to push this as an array */ + return ucl_object_lua_push_array (L, obj); + } + + /* Optimize allocation by preallocation of table */ + while (ucl_iterate_object (obj, &it, true) != NULL) { + nelt ++; + } + + lua_createtable (L, 0, nelt); + it = NULL; + + while ((cur = ucl_iterate_object (obj, &it, true)) != NULL) { + ucl_object_lua_push_element (L, ucl_object_key (cur), cur); + } + + return 1; +} + +/** + * Push an array to lua as table indexed by integers + * @param L + * @param obj + * @return + */ +static int +ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj) +{ + const ucl_object_t *cur; + int i = 1, nelt = 0; + + /* Optimize allocation by preallocation of table */ + LL_FOREACH (obj, cur) { + nelt ++; + } + + lua_createtable (L, nelt, 0); + + LL_FOREACH (obj, cur) { + ucl_object_push_lua (L, cur, false); + lua_rawseti (L, -2, i); + i ++; + } + + return 1; +} + +/** + * Push a simple object to lua depending on its actual type + */ +static int +ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, + bool allow_array) +{ + struct ucl_lua_funcdata *fd; + + if (allow_array && obj->next != NULL) { + /* Actually we need to push this as an array */ + return ucl_object_lua_push_array (L, obj); + } + + switch (obj->type) { + case UCL_BOOLEAN: + lua_pushboolean (L, ucl_obj_toboolean (obj)); + break; + case UCL_STRING: + lua_pushstring (L, ucl_obj_tostring (obj)); + break; + case UCL_INT: +#if LUA_VERSION_NUM >= 501 + lua_pushinteger (L, ucl_obj_toint (obj)); +#else + lua_pushnumber (L, ucl_obj_toint (obj)); +#endif + break; + case UCL_FLOAT: + case UCL_TIME: + lua_pushnumber (L, ucl_obj_todouble (obj)); + break; + case UCL_NULL: + lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null"); + break; + case UCL_USERDATA: + fd = (struct ucl_lua_funcdata *)obj->value.ud; + lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx); + break; + default: + lua_pushnil (L); + break; + } + + return 1; +} + +/*** + * @function ucl_object_push_lua(L, obj, allow_array) + * This is a `C` function to push `UCL` object as lua variable. This function + * converts `obj` to lua representation using the following conversions: + * + * - *scalar* values are directly presented by lua objects + * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`, + * this can be used to pass functions from lua to c and vice-versa + * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations + * - *objects* are converted to lua tables with string indicies + * @param {lua_State} L lua state pointer + * @param {ucl_object_t} obj object to push + * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays) + * @return {int} `1` if an object is pushed to lua + */ +int +ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array) +{ + switch (obj->type) { + case UCL_OBJECT: + return ucl_object_lua_push_object (L, obj, allow_array); + case UCL_ARRAY: + return ucl_object_lua_push_array (L, obj->value.av); + default: + return ucl_object_lua_push_scalar (L, obj, allow_array); + } +} + +/** + * Parse lua table into object top + * @param L + * @param top + * @param idx + */ +static ucl_object_t * +ucl_object_lua_fromtable (lua_State *L, int idx) +{ + ucl_object_t *obj, *top = NULL; + size_t keylen; + const char *k; + bool is_array = true; + int max = INT_MIN; + + if (idx < 0) { + /* For negative indicies we want to invert them */ + idx = lua_gettop (L) + idx + 1; + } + /* Check for array */ + lua_pushnil (L); + while (lua_next (L, idx) != 0) { + if (lua_type (L, -2) == LUA_TNUMBER) { + double num = lua_tonumber (L, -2); + if (num == (int)num) { + if (num > max) { + max = num; + } + } + else { + /* Keys are not integer */ + lua_pop (L, 2); + is_array = false; + break; + } + } + else { + /* Keys are not numeric */ + lua_pop (L, 2); + is_array = false; + break; + } + lua_pop (L, 1); + } + + /* Table iterate */ + if (is_array) { + int i; + + top = ucl_object_typed_new (UCL_ARRAY); + for (i = 1; i <= max; i ++) { + lua_pushinteger (L, i); + lua_gettable (L, idx); + obj = ucl_object_lua_fromelt (L, lua_gettop (L)); + if (obj != NULL) { + ucl_array_append (top, obj); + } + } + } + else { + lua_pushnil (L); + top = ucl_object_typed_new (UCL_OBJECT); + while (lua_next (L, idx) != 0) { + /* copy key to avoid modifications */ + k = lua_tolstring (L, -2, &keylen); + obj = ucl_object_lua_fromelt (L, lua_gettop (L)); + + if (obj != NULL) { + ucl_object_insert_key (top, obj, k, keylen, true); + } + lua_pop (L, 1); + } + } + + return top; +} + +/** + * Get a single element from lua to object obj + * @param L + * @param obj + * @param idx + */ +static ucl_object_t * +ucl_object_lua_fromelt (lua_State *L, int idx) +{ + int type; + double num; + ucl_object_t *obj = NULL; + struct ucl_lua_funcdata *fd; + + type = lua_type (L, idx); + + switch (type) { + case LUA_TSTRING: + obj = ucl_object_fromstring_common (lua_tostring (L, idx), 0, 0); + break; + case LUA_TNUMBER: + num = lua_tonumber (L, idx); + if (num == (int64_t)num) { + obj = ucl_object_fromint (num); + } + else { + obj = ucl_object_fromdouble (num); + } + break; + case LUA_TBOOLEAN: + obj = ucl_object_frombool (lua_toboolean (L, idx)); + break; + case LUA_TUSERDATA: + if (lua_topointer (L, idx) == ucl_null) { + obj = ucl_object_typed_new (UCL_NULL); + } + break; + case LUA_TTABLE: + case LUA_TFUNCTION: + case LUA_TTHREAD: + if (luaL_getmetafield (L, idx, "__gen_ucl")) { + if (lua_isfunction (L, -1)) { + lua_settop (L, 3); /* gen, obj, func */ + lua_insert (L, 1); /* func, gen, obj */ + lua_insert (L, 2); /* func, obj, gen */ + lua_call(L, 2, 1); + obj = ucl_object_lua_fromelt (L, 1); + } + lua_pop (L, 2); + } + else { + if (type == LUA_TTABLE) { + obj = ucl_object_lua_fromtable (L, idx); + } + else if (type == LUA_TFUNCTION) { + fd = malloc (sizeof (*fd)); + if (fd != NULL) { + lua_pushvalue (L, idx); + fd->L = L; + fd->ret = NULL; + fd->idx = luaL_ref (L, LUA_REGISTRYINDEX); + + obj = ucl_object_new_userdata (lua_ucl_userdata_dtor, + lua_ucl_userdata_emitter); + obj->type = UCL_USERDATA; + obj->value.ud = (void *)fd; + } + } + } + break; + } + + return obj; +} + +/** + * @function ucl_object_lua_import(L, idx) + * Extracts ucl object from lua variable at `idx` position, + * @see ucl_object_push_lua for conversion definitions + * @param {lua_state} L lua state machine pointer + * @param {int} idx index where the source variable is placed + * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1, + * this object thus needs to be unref'ed after usage. + */ +ucl_object_t * +ucl_object_lua_import (lua_State *L, int idx) +{ + ucl_object_t *obj; + int t; + + t = lua_type (L, idx); + switch (t) { + case LUA_TTABLE: + obj = ucl_object_lua_fromtable (L, idx); + break; + default: + obj = ucl_object_lua_fromelt (L, idx); + break; + } + + return obj; +} + +static int +lua_ucl_parser_init (lua_State *L) +{ + struct ucl_parser *parser, **pparser; + int flags = 0; + + if (lua_gettop (L) >= 1) { + flags = lua_tonumber (L, 1); + } + + parser = ucl_parser_new (flags); + if (parser == NULL) { + lua_pushnil (L); + } + + pparser = lua_newuserdata (L, sizeof (parser)); + *pparser = parser; + luaL_getmetatable (L, PARSER_META); + lua_setmetatable (L, -2); + + return 1; +} + +static struct ucl_parser * +lua_ucl_parser_get (lua_State *L, int index) +{ + return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META)); +} + +/*** + * @method parser:parse_file(name) + * Parse UCL object from file. + * @param {string} name filename to parse + * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned +@example +local parser = ucl.parser() +local res,err = parser:parse_file('/some/file.conf') + +if not res then + print('parser error: ' .. err) +else + -- Do something with object +end + */ +static int +lua_ucl_parser_parse_file (lua_State *L) +{ + struct ucl_parser *parser; + const char *file; + int ret = 2; + + parser = lua_ucl_parser_get (L, 1); + file = luaL_checkstring (L, 2); + + if (parser != NULL && file != NULL) { + if (ucl_parser_add_file (parser, file)) { + lua_pushboolean (L, true); + ret = 1; + } + else { + lua_pushboolean (L, false); + lua_pushstring (L, ucl_parser_get_error (parser)); + } + } + else { + lua_pushboolean (L, false); + lua_pushstring (L, "invalid arguments"); + } + + return ret; +} + +/*** + * @method parser:parse_string(input) + * Parse UCL object from file. + * @param {string} input string to parse + * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned + */ +static int +lua_ucl_parser_parse_string (lua_State *L) +{ + struct ucl_parser *parser; + const char *string; + size_t llen; + int ret = 2; + + parser = lua_ucl_parser_get (L, 1); + string = luaL_checklstring (L, 2, &llen); + + if (parser != NULL && string != NULL) { + if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) { + lua_pushboolean (L, true); + ret = 1; + } + else { + lua_pushboolean (L, false); + lua_pushstring (L, ucl_parser_get_error (parser)); + } + } + else { + lua_pushboolean (L, false); + lua_pushstring (L, "invalid arguments"); + } + + return ret; +} + +/*** + * @method parser:get_object() + * Get top object from parser and export it to lua representation. + * @return {variant or nil} ucl object as lua native variable + */ +static int +lua_ucl_parser_get_object (lua_State *L) +{ + struct ucl_parser *parser; + ucl_object_t *obj; + int ret = 1; + + parser = lua_ucl_parser_get (L, 1); + obj = ucl_parser_get_object (parser); + + if (obj != NULL) { + ret = ucl_object_push_lua (L, obj, false); + /* no need to keep reference */ + ucl_object_unref (obj); + } + else { + lua_pushnil (L); + } + + return ret; +} + +static int +lua_ucl_parser_gc (lua_State *L) +{ + struct ucl_parser *parser; + + parser = lua_ucl_parser_get (L, 1); + ucl_parser_free (parser); + + return 0; +} + +static void +lua_ucl_parser_mt (lua_State *L) +{ + luaL_newmetatable (L, PARSER_META); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction (L, lua_ucl_parser_gc); + lua_setfield (L, -2, "__gc"); + + lua_pushcfunction (L, lua_ucl_parser_parse_file); + lua_setfield (L, -2, "parse_file"); + + lua_pushcfunction (L, lua_ucl_parser_parse_string); + lua_setfield (L, -2, "parse_string"); + + lua_pushcfunction (L, lua_ucl_parser_get_object); + lua_setfield (L, -2, "get_object"); + + lua_pop (L, 1); +} + +static int +lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type) +{ + unsigned char *result; + + result = ucl_object_emit (obj, type); + + if (result != NULL) { + lua_pushstring (L, (const char *)result); + free (result); + } + else { + lua_pushnil (L); + } + + return 1; +} + +static int +lua_ucl_to_json (lua_State *L) +{ + ucl_object_t *obj; + int format = UCL_EMIT_JSON; + + if (lua_gettop (L) > 1) { + if (lua_toboolean (L, 2)) { + format = UCL_EMIT_JSON_COMPACT; + } + } + + obj = ucl_object_lua_import (L, 1); + if (obj != NULL) { + lua_ucl_to_string (L, obj, format); + ucl_object_unref (obj); + } + else { + lua_pushnil (L); + } + + return 1; +} + +static int +lua_ucl_to_config (lua_State *L) +{ + ucl_object_t *obj; + + obj = ucl_object_lua_import (L, 1); + if (obj != NULL) { + lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG); + ucl_object_unref (obj); + } + else { + lua_pushnil (L); + } + + return 1; +} + +/*** + * @function ucl.to_format(var, format) + * Converts lua variable `var` to the specified `format`. Formats supported are: + * + * - `json` - fine printed json + * - `json-compact` - compacted json + * - `config` - fine printed configuration + * - `ucl` - same as `config` + * - `yaml` - embedded yaml + * + * If `var` contains function, they are called during output formatting and if + * they return string value, then this value is used for ouptut. + * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output) + * @param {string} format any available format + * @return {string} string representation of `var` in the specific `format`. + * @example +local table = { + str = 'value', + num = 100500, + null = ucl.null, + func = function () + return 'huh' + end +} + +print(ucl.to_format(table, 'ucl')) +-- Output: +--[[ +num = 100500; +str = "value"; +null = null; +func = "huh"; +--]] + */ +static int +lua_ucl_to_format (lua_State *L) +{ + ucl_object_t *obj; + int format = UCL_EMIT_JSON; + + if (lua_gettop (L) > 1) { + if (lua_type (L, 2) == LUA_TNUMBER) { + format = lua_tonumber (L, 2); + if (format < 0 || format >= UCL_EMIT_YAML) { + lua_pushnil (L); + return 1; + } + } + else if (lua_type (L, 2) == LUA_TSTRING) { + const char *strtype = lua_tostring (L, 2); + + if (strcasecmp (strtype, "json") == 0) { + format = UCL_EMIT_JSON; + } + else if (strcasecmp (strtype, "json-compact") == 0) { + format = UCL_EMIT_JSON_COMPACT; + } + else if (strcasecmp (strtype, "yaml") == 0) { + format = UCL_EMIT_YAML; + } + else if (strcasecmp (strtype, "config") == 0 || + strcasecmp (strtype, "ucl") == 0) { + format = UCL_EMIT_CONFIG; + } + } + } + + obj = ucl_object_lua_import (L, 1); + if (obj != NULL) { + lua_ucl_to_string (L, obj, format); + ucl_object_unref (obj); + } + else { + lua_pushnil (L); + } + + return 1; +} + +static int +lua_ucl_null_tostring (lua_State* L) +{ + lua_pushstring (L, "null"); + return 1; +} + +static void +lua_ucl_null_mt (lua_State *L) +{ + luaL_newmetatable (L, NULL_META); + + lua_pushcfunction (L, lua_ucl_null_tostring); + lua_setfield (L, -2, "__tostring"); + + lua_pop (L, 1); +} + +int +luaopen_ucl (lua_State *L) +{ + lua_ucl_parser_mt (L); + lua_ucl_null_mt (L); + + /* Create the refs weak table: */ + lua_createtable (L, 0, 2); + lua_pushliteral (L, "v"); /* tbl, "v" */ + lua_setfield (L, -2, "__mode"); + lua_pushvalue (L, -1); /* tbl, tbl */ + lua_setmetatable (L, -2); /* tbl */ + lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs"); + + lua_newtable (L); + + lua_pushcfunction (L, lua_ucl_parser_init); + lua_setfield (L, -2, "parser"); + + lua_pushcfunction (L, lua_ucl_to_json); + lua_setfield (L, -2, "to_json"); + + lua_pushcfunction (L, lua_ucl_to_config); + lua_setfield (L, -2, "to_config"); + + lua_pushcfunction (L, lua_ucl_to_format); + lua_setfield (L, -2, "to_format"); + + ucl_null = lua_newuserdata (L, 0); + luaL_getmetatable (L, NULL_META); + lua_setmetatable (L, -2); + + lua_pushvalue (L, -1); + lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null"); + + lua_setfield (L, -2, "null"); + + return 1; +} + +struct ucl_lua_funcdata* +ucl_object_toclosure (const ucl_object_t *obj) +{ + if (obj == NULL || obj->type != UCL_USERDATA) { + return NULL; + } + + return (struct ucl_lua_funcdata*)obj->value.ud; +} diff --git a/contrib/libucl/lua/test.lua b/contrib/libucl/lua/test.lua new file mode 100644 index 000000000000..1e7b3b3e0bdb --- /dev/null +++ b/contrib/libucl/lua/test.lua @@ -0,0 +1,48 @@ +local ucl = require("ucl") + +function test_simple() + local expect = + '['.. + '"float",1.5,'.. + '"integer",5,'.. + '"true",true,'.. + '"false",false,'.. + '"null",null,'.. + '"string","hello",'.. + '"array",[1,2],'.. + '"object",{"key":"value"}'.. + ']' + + -- Input to to_value matches the output of to_string: + local parser = ucl.parser() + local res,err = parser:parse_string(expect) + if not res then + print('parser error: ' .. err) + return 1 + end + + local obj = parser:get_object() + local got = ucl.to_json(obj, true) + if expect == got then + return 0 + else + print(expect .. " == " .. tostring(got)) + return 1 + end +end + +test_simple() + +local table = { + str = 'value', + num = 100500, + null = ucl.null, + func = function () + return 'huh' + end, + badfunc = function() + print("I'm bad") + end +} + +print(ucl.to_format(table, 'ucl')) diff --git a/contrib/libucl/m4/.gitignore b/contrib/libucl/m4/.gitignore new file mode 100644 index 000000000000..5e7d2734cfc6 --- /dev/null +++ b/contrib/libucl/m4/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore diff --git a/contrib/libucl/m4/ax_lua.m4 b/contrib/libucl/m4/ax_lua.m4 new file mode 100644 index 000000000000..7662f4f22d1b --- /dev/null +++ b/contrib/libucl/m4/ax_lua.m4 @@ -0,0 +1,606 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_lua.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] +# +# DESCRIPTION +# +# Detect a Lua interpreter, optionally specifying a minimum and maximum +# version number. Set up important Lua paths, such as the directories in +# which to install scripts and modules (shared libraries). +# +# Also detect Lua headers and libraries. The Lua version contained in the +# header is checked to match the Lua interpreter version exactly. When +# searching for Lua libraries, the version number is used as a suffix. +# This is done with the goal of supporting multiple Lua installs (5.1 and +# 5.2 side-by-side). +# +# A note on compatibility with previous versions: This file has been +# mostly rewritten for serial 18. Most developers should be able to use +# these macros without needing to modify configure.ac. Care has been taken +# to preserve each macro's behavior, but there are some differences: +# +# 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as +# AX_PROG_LUA with no arguments. +# +# 2) AX_LUA_HEADERS now checks that the version number defined in lua.h +# matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore +# unnecessary, so it is deprecated and does not expand to anything. +# +# 3) The configure flag --with-lua-suffix no longer exists; the user +# should instead specify the LUA precious variable on the command line. +# See the AX_PROG_LUA description for details. +# +# Please read the macro descriptions below for more information. +# +# This file was inspired by Andrew Dalke's and James Henstridge's +# python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4 +# (serial 17). Basically, this file is a mash-up of those two files. I +# like to think it combines the best of the two! +# +# AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua +# paths. Adds precious variable LUA, which may contain the path of the Lua +# interpreter. If LUA is blank, the user's path is searched for an +# suitable interpreter. +# +# If MINIMUM-VERSION is supplied, then only Lua interpreters with a +# version number greater or equal to MINIMUM-VERSION will be accepted. If +# TOO-BIG- VERSION is also supplied, then only Lua interpreters with a +# version number greater or equal to MINIMUM-VERSION and less than +# TOO-BIG-VERSION will be accepted. +# +# The Lua version number, LUA_VERSION, is found from the interpreter, and +# substituted. LUA_PLATFORM is also found, but not currently supported (no +# standard representation). +# +# Finally, the macro finds four paths: +# +# luadir Directory to install Lua scripts. +# pkgluadir $luadir/$PACKAGE +# luaexecdir Directory to install Lua modules. +# pkgluaexecdir $luaexecdir/$PACKAGE +# +# These paths a found based on $prefix, $exec_prefix, Lua's package.path, +# and package.cpath. The first path of package.path beginning with $prefix +# is selected as luadir. The first path of package.cpath beginning with +# $exec_prefix is used as luaexecdir. This should work on all reasonable +# Lua installations. If a path cannot be determined, a default path is +# used. Of course, the user can override these later when invoking make. +# +# luadir Default: $prefix/share/lua/$LUA_VERSION +# luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION +# +# These directories can be used by Automake as install destinations. The +# variable name minus 'dir' needs to be used as a prefix to the +# appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES. +# +# If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is +# performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT- +# FOUND is blank, then it will default to printing an error. To prevent +# the default behavior, give ':' as an action. +# +# AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be +# expanded before this macro. Adds precious variable LUA_INCLUDE, which +# may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If +# LUA_INCLUDE is blank, then this macro will attempt to find suitable +# flags. +# +# LUA_INCLUDE can be used by Automake to compile Lua modules or +# executables with embedded interpreters. The *_CPPFLAGS variables should +# be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE). +# +# This macro searches for the header lua.h (and others). The search is +# performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE. +# If the search is unsuccessful, then some common directories are tried. +# If the headers are then found, then LUA_INCLUDE is set accordingly. +# +# The paths automatically searched are: +# +# * /usr/include/luaX.Y +# * /usr/include/lua/X.Y +# * /usr/include/luaXY +# * /usr/local/include/luaX.Y +# * /usr/local/include/lua-X.Y +# * /usr/local/include/lua/X.Y +# * /usr/local/include/luaXY +# +# (Where X.Y is the Lua version number, e.g. 5.1.) +# +# The Lua version number found in the headers is always checked to match +# the Lua interpreter's version number. Lua headers with mismatched +# version numbers are not accepted. +# +# If headers are found, then ACTION-IF-FOUND is performed, otherwise +# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then +# it will default to printing an error. To prevent the default behavior, +# set the action to ':'. +# +# AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be +# expanded before this macro. Adds precious variable LUA_LIB, which may +# contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank, +# then this macro will attempt to find suitable flags. +# +# LUA_LIB can be used by Automake to link Lua modules or executables with +# embedded interpreters. The *_LIBADD and *_LDADD variables should be used +# for this purpose, e.g. mymod_LIBADD = $(LUA_LIB). +# +# This macro searches for the Lua library. More technically, it searches +# for a library containing the function lua_load. The search is performed +# with a combination of LIBS, LIBRARY_PATH, and LUA_LIB. +# +# If the search determines that some linker flags are missing, then those +# flags will be added to LUA_LIB. +# +# If libraries are found, then ACTION-IF-FOUND is performed, otherwise +# ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then +# it will default to printing an error. To prevent the default behavior, +# set the action to ':'. +# +# AX_LUA_READLINE: Search for readline headers and libraries. Requires the +# AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the +# Autoconf Archive. +# +# If a readline compatible library is found, then ACTION-IF-FOUND is +# performed, otherwise ACTION-IF-NOT-FOUND is performed. +# +# LICENSE +# +# Copyright (c) 2014 Reuben Thomas +# Copyright (c) 2013 Tim Perkins +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 23 + +dnl ========================================================================= +dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION], +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ========================================================================= +AC_DEFUN([AX_PROG_LUA], +[ + dnl Make LUA a precious variable. + AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1]) + + dnl Find a Lua interpreter. + m4_define_default([_AX_LUA_INTERPRETER_LIST], + [lua lua5.2 lua52 lua5.1 lua51 lua50]) + + m4_if([$1], [], + [ dnl No version check is needed. Find any Lua interpreter. + AS_IF([test "x$LUA" = 'x'], + [AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])]) + ax_display_LUA='lua' + + dnl At least check if this is a Lua interpreter. + AC_MSG_CHECKING([if $LUA is a Lua interpreter]) + _AX_LUA_CHK_IS_INTRP([$LUA], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([not a Lua interpreter]) + ]) + ], + [ dnl A version check is needed. + AS_IF([test "x$LUA" != 'x'], + [ dnl Check if this is a Lua interpreter. + AC_MSG_CHECKING([if $LUA is a Lua interpreter]) + _AX_LUA_CHK_IS_INTRP([$LUA], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([not a Lua interpreter]) + ]) + dnl Check the version. + m4_if([$2], [], + [_ax_check_text="whether $LUA version >= $1"], + [_ax_check_text="whether $LUA version >= $1, < $2"]) + AC_MSG_CHECKING([$_ax_check_text]) + _AX_LUA_CHK_VER([$LUA], [$1], [$2], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([version is out of range for specified LUA])]) + ax_display_LUA=$LUA + ], + [ dnl Try each interpreter until we find one that satisfies VERSION. + m4_if([$2], [], + [_ax_check_text="for a Lua interpreter with version >= $1"], + [_ax_check_text="for a Lua interpreter with version >= $1, < $2"]) + AC_CACHE_CHECK([$_ax_check_text], + [ax_cv_pathless_LUA], + [ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do + test "x$ax_cv_pathless_LUA" = 'xnone' && break + _AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue]) + _AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break]) + done + ]) + dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA. + AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'], + [LUA=':'], + [AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])]) + ax_display_LUA=$ax_cv_pathless_LUA + ]) + ]) + + AS_IF([test "x$LUA" = 'x:'], + [ dnl Run any user-specified action, or abort. + m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])]) + ], + [ dnl Query Lua for its version number. + AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], + [ ax_cv_lua_version=`$LUA -e 'print(_VERSION:match "(%d+%.%d+)")'` ]) + AS_IF([test "x$ax_cv_lua_version" = 'x'], + [AC_MSG_ERROR([invalid Lua version number])]) + AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) + AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | sed 's|\.||'`]) + + dnl The following check is not supported: + dnl At times (like when building shared libraries) you may want to know + dnl which OS platform Lua thinks this is. + AC_CACHE_CHECK([for $ax_display_LUA platform], [ax_cv_lua_platform], + [ax_cv_lua_platform=`$LUA -e "print('unknown')"`]) + AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform]) + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct + dnl variables so they can be overridden if need be. However, the general + dnl consensus is that you shouldn't need this ability. + AC_SUBST([LUA_PREFIX], ['${prefix}']) + AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}']) + + dnl Lua provides no way to query the script directory, and instead + dnl provides LUA_PATH. However, we should be able to make a safe educated + dnl guess. If the built-in search path contains a directory which is + dnl prefixed by $prefix, then we can store scripts there. The first + dnl matching path will be used. + AC_CACHE_CHECK([for $ax_display_LUA script directory], + [ax_cv_lua_luadir], + [ AS_IF([test "x$prefix" = 'xNONE'], + [ax_lua_prefix=$ac_default_prefix], + [ax_lua_prefix=$prefix]) + + dnl Initialize to the default path. + ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" + + dnl Try to find a path with the prefix. + _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [package.path]) + AS_IF([test "x$ax_lua_prefixed_path" != 'x'], + [ dnl Fix the prefix. + _ax_strip_prefix=`echo "$ax_lua_prefix" | sed 's|.|.|g'` + ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \ + sed "s,^$_ax_strip_prefix,$LUA_PREFIX,"` + ]) + ]) + AC_SUBST([luadir], [$ax_cv_lua_luadir]) + AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE]) + + dnl Lua provides no way to query the module directory, and instead + dnl provides LUA_PATH. However, we should be able to make a safe educated + dnl guess. If the built-in search path contains a directory which is + dnl prefixed by $exec_prefix, then we can store modules there. The first + dnl matching path will be used. + AC_CACHE_CHECK([for $ax_display_LUA module directory], + [ax_cv_lua_luaexecdir], + [ AS_IF([test "x$exec_prefix" = 'xNONE'], + [ax_lua_exec_prefix=$ax_lua_prefix], + [ax_lua_exec_prefix=$exec_prefix]) + + dnl Initialize to the default path. + ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION" + + dnl Try to find a path with the prefix. + _AX_LUA_FND_PRFX_PTH([$LUA], + [$ax_lua_exec_prefix], [package.cpathd]) + AS_IF([test "x$ax_lua_prefixed_path" != 'x'], + [ dnl Fix the prefix. + _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | sed 's|.|.|g'` + ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \ + sed "s,^$_ax_strip_prefix,$LUA_EXEC_PREFIX,"` + ]) + ]) + AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir]) + AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE]) + + dnl Run any user specified action. + $3 + ]) +]) + +dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA. +AC_DEFUN([AX_WITH_LUA], +[ + AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA]]) + AX_PROG_LUA +]) + + +dnl ========================================================================= +dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +dnl ========================================================================= +AC_DEFUN([_AX_LUA_CHK_IS_INTRP], +[ + dnl Just print _VERSION because all Lua interpreters have this global. + AS_IF([$1 -e "print('Hello ' .. _VERSION .. '!')" &>/dev/null], + [$2], [$3]) +]) + + +dnl ========================================================================= +dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION], +dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +dnl ========================================================================= +AC_DEFUN([_AX_LUA_CHK_VER], +[ + AS_IF([$1 2>/dev/null -e ' + function norm (v) i,j=v:match "(%d+)%.(%d+)" return 100 * i + j end + v=norm (_VERSION) + os.exit ((v >= norm ("$2") and ("$3" == "" or v < norm ("$3"))) and 0 or 1)'], + [$4], [$5]) +]) + + +dnl ========================================================================= +dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, LUA-PATH-VARIABLE) +dnl ========================================================================= +AC_DEFUN([_AX_LUA_FND_PRFX_PTH], +[ + dnl Invokes the Lua interpreter PROG to print the path variable + dnl LUA-PATH-VARIABLE, usually package.path or package.cpath. Paths are + dnl then matched against PREFIX. The first path to begin with PREFIX is set + dnl to ax_lua_prefixed_path. + + ax_lua_prefixed_path='' + _ax_package_paths=`$1 -e 'print($3)' 2>/dev/null | sed 's|;|\n|g'` + dnl Try the paths in order, looking for the prefix. + for _ax_package_path in $_ax_package_paths; do + dnl Copy the path, up to the use of a Lua wildcard. + _ax_path_parts=`echo "$_ax_package_path" | sed 's|/|\n|g'` + _ax_reassembled='' + for _ax_path_part in $_ax_path_parts; do + echo "$_ax_path_part" | grep '\?' >/dev/null && break + _ax_reassembled="$_ax_reassembled/$_ax_path_part" + done + dnl Check the path against the prefix. + _ax_package_path=$_ax_reassembled + if echo "$_ax_package_path" | grep "^$2" >/dev/null; then + dnl Found it. + ax_lua_prefixed_path=$_ax_package_path + break + fi + done +]) + + +dnl ========================================================================= +dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ========================================================================= +AC_DEFUN([AX_LUA_HEADERS], +[ + dnl Check for LUA_VERSION. + AC_MSG_CHECKING([if LUA_VERSION is defined]) + AS_IF([test "x$LUA_VERSION" != 'x'], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION]) + ]) + + dnl Make LUA_INCLUDE a precious variable. + AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1]) + + dnl Some default directories to search. + LUA_SHORT_VERSION=`echo "$LUA_VERSION" | sed 's|\.||'` + m4_define_default([_AX_LUA_INCLUDE_LIST], + [ /usr/include/lua$LUA_VERSION \ + /usr/include/lua/$LUA_VERSION \ + /usr/include/lua$LUA_SHORT_VERSION \ + /usr/local/include/lua$LUA_VERSION \ + /usr/local/include/lua-$LUA_VERSION \ + /usr/local/include/lua/$LUA_VERSION \ + /usr/local/include/lua$LUA_SHORT_VERSION \ + ]) + + dnl Try to find the headers. + _ax_lua_saved_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" + AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) + CPPFLAGS=$_ax_lua_saved_cppflags + + dnl Try some other directories if LUA_INCLUDE was not set. + AS_IF([test "x$LUA_INCLUDE" = 'x' && + test "x$ac_cv_header_lua_h" != 'xyes'], + [ dnl Try some common include paths. + for _ax_include_path in _AX_LUA_INCLUDE_LIST; do + test ! -d "$_ax_include_path" && continue + + AC_MSG_CHECKING([for Lua headers in]) + AC_MSG_RESULT([$_ax_include_path]) + + AS_UNSET([ac_cv_header_lua_h]) + AS_UNSET([ac_cv_header_lualib_h]) + AS_UNSET([ac_cv_header_lauxlib_h]) + AS_UNSET([ac_cv_header_luaconf_h]) + + _ax_lua_saved_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I$_ax_include_path" + AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) + CPPFLAGS=$_ax_lua_saved_cppflags + + AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], + [ LUA_INCLUDE="-I$_ax_include_path" + break + ]) + done + ]) + + AS_IF([test "x$ac_cv_header_lua_h" = 'xyes' && test "x$cross_compiling" != 'xyes'], + [ dnl Make a program to print LUA_VERSION defined in the header. + dnl TODO This probably shouldn't be a runtime test. + + AC_CACHE_CHECK([for Lua header version], + [ax_cv_lua_header_version], + [ _ax_lua_saved_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" + AC_RUN_IFELSE( + [ AC_LANG_SOURCE([[ +#include +#include +#include +int main(int argc, char ** argv) +{ + if(argc > 1) printf("%s", LUA_VERSION); + exit(EXIT_SUCCESS); +} +]]) + ], + [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \ + sed "s|^Lua \(.*\)|\1|" | \ + grep -o "^@<:@0-9@:>@\+\\.@<:@0-9@:>@\+"` + ], + [ax_cv_lua_header_version='unknown']) + CPPFLAGS=$_ax_lua_saved_cppflags + ]) + + dnl Compare this to the previously found LUA_VERSION. + AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION]) + AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"], + [ AC_MSG_RESULT([yes]) + ax_header_version_match='yes' + ], + [ AC_MSG_RESULT([no]) + ax_header_version_match='no' + ]) + ], + [ + ax_header_version_match='yes' + ]) + + dnl Was LUA_INCLUDE specified? + AS_IF([test "x$ax_header_version_match" != 'xyes' && + test "x$LUA_INCLUDE" != 'x'], + [AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])]) + + dnl Test the final result and run user code. + AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1], + [m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])]) +]) + +dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS. +AC_DEFUN([AX_LUA_HEADERS_VERSION], +[ + AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS]]) +]) + + +dnl ========================================================================= +dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ========================================================================= +AC_DEFUN([AX_LUA_LIBS], +[ + dnl TODO Should this macro also check various -L flags? + + dnl Check for LUA_VERSION. + AC_MSG_CHECKING([if LUA_VERSION is defined]) + AS_IF([test "x$LUA_VERSION" != 'x'], + [AC_MSG_RESULT([yes])], + [ AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION]) + ]) + + dnl Make LUA_LIB a precious variable. + AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1]) + + AS_IF([test "x$LUA_LIB" != 'x'], + [ dnl Check that LUA_LIBS works. + _ax_lua_saved_libs=$LIBS + LIBS="$LIBS $LUA_LIB" + AC_SEARCH_LIBS([lua_load], [], + [_ax_found_lua_libs='yes'], + [_ax_found_lua_libs='no']) + LIBS=$_ax_lua_saved_libs + + dnl Check the result. + AS_IF([test "x$_ax_found_lua_libs" != 'xyes'], + [AC_MSG_ERROR([cannot find libs for specified LUA_LIB])]) + ], + [ dnl First search for extra libs. + _ax_lua_extra_libs='' + + _ax_lua_saved_libs=$LIBS + LIBS="$LIBS $LUA_LIB" + AC_SEARCH_LIBS([exp], [m]) + AC_SEARCH_LIBS([dlopen], [dl]) + LIBS=$_ax_lua_saved_libs + + AS_IF([test "x$ac_cv_search_exp" != 'xno' && + test "x$ac_cv_search_exp" != 'xnone required'], + [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"]) + + AS_IF([test "x$ac_cv_search_dlopen" != 'xno' && + test "x$ac_cv_search_dlopen" != 'xnone required'], + [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"]) + + dnl Try to find the Lua libs. + _ax_lua_saved_libs=$LIBS + LIBS="$LIBS $LUA_LIB" + AC_SEARCH_LIBS([lua_load], + [ lua$LUA_VERSION \ + lua$LUA_SHORT_VERSION \ + lua-$LUA_VERSION \ + lua-$LUA_SHORT_VERSION \ + lua], + [_ax_found_lua_libs='yes'], + [_ax_found_lua_libs='no'], + [$_ax_lua_extra_libs]) + LIBS=$_ax_lua_saved_libs + + AS_IF([test "x$ac_cv_search_lua_load" != 'xno' && + test "x$ac_cv_search_lua_load" != 'xnone required'], + [LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"]) + ]) + + dnl Test the result and run user code. + AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1], + [m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])]) +]) + + +dnl ========================================================================= +dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ========================================================================= +AC_DEFUN([AX_LUA_READLINE], +[ + AX_LIB_READLINE + AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' && + test "x$ac_cv_header_readline_history_h" != 'x'], + [ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS" + $1 + ], + [$2]) +]) diff --git a/contrib/libucl/src/ucl_emitter.c b/contrib/libucl/src/ucl_emitter.c index 11fe50c00602..8134d09c1a65 100644 --- a/contrib/libucl/src/ucl_emitter.c +++ b/contrib/libucl/src/ucl_emitter.c @@ -130,6 +130,19 @@ ucl_emitter_print_key (bool print_key, struct ucl_emitter_context *ctx, func->ucl_emitter_append_character (' ', 1, func->ud); } } + else if (ctx->id == UCL_EMIT_YAML) { + if (obj->keylen > 0 && (obj->flags & UCL_OBJECT_NEED_KEY_ESCAPE)) { + ucl_elt_string_write_json (obj->key, obj->keylen, ctx); + } + else if (obj->keylen > 0) { + func->ucl_emitter_append_len (obj->key, obj->keylen, func->ud); + } + else { + func->ucl_emitter_append_len ("null", 4, func->ud); + } + + func->ucl_emitter_append_len (": ", 2, func->ud); + } else { if (obj->keylen > 0) { ucl_elt_string_write_json (obj->key, obj->keylen, ctx); @@ -182,7 +195,7 @@ ucl_emitter_common_end_object (struct ucl_emitter_context *ctx, const struct ucl_emitter_functions *func = ctx->func; if (UCL_EMIT_IDENT_TOP_OBJ(ctx, obj)) { - ctx->ident --; + ctx->indent --; if (compact) { func->ucl_emitter_append_character ('}', 1, func->ud); } @@ -191,7 +204,7 @@ ucl_emitter_common_end_object (struct ucl_emitter_context *ctx, /* newline is already added for this format */ func->ucl_emitter_append_character ('\n', 1, func->ud); } - ucl_add_tabs (func, ctx->ident, compact); + ucl_add_tabs (func, ctx->indent, compact); func->ucl_emitter_append_character ('}', 1, func->ud); } } @@ -210,7 +223,7 @@ ucl_emitter_common_end_array (struct ucl_emitter_context *ctx, { const struct ucl_emitter_functions *func = ctx->func; - ctx->ident --; + ctx->indent --; if (compact) { func->ucl_emitter_append_character (']', 1, func->ud); } @@ -219,7 +232,7 @@ ucl_emitter_common_end_array (struct ucl_emitter_context *ctx, /* newline is already added for this format */ func->ucl_emitter_append_character ('\n', 1, func->ud); } - ucl_add_tabs (func, ctx->ident, compact); + ucl_add_tabs (func, ctx->indent, compact); func->ucl_emitter_append_character (']', 1, func->ud); } @@ -249,7 +262,7 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx, func->ucl_emitter_append_len ("[\n", 2, func->ud); } - ctx->ident ++; + ctx->indent ++; if (obj->type == UCL_ARRAY) { /* explicit array */ @@ -294,7 +307,7 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx, else { func->ucl_emitter_append_len ("{\n", 2, func->ud); } - ctx->ident ++; + ctx->indent ++; } while ((cur = ucl_hash_iterate (obj->value.ov, &it))) { @@ -315,7 +328,7 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx, func->ucl_emitter_append_len (",\n", 2, func->ud); } } - ucl_add_tabs (func, ctx->ident, compact); + ucl_add_tabs (func, ctx->indent, compact); ucl_emitter_common_start_array (ctx, cur, true, compact); ucl_emitter_common_end_array (ctx, cur, compact); } @@ -342,17 +355,23 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx, { const struct ucl_emitter_functions *func = ctx->func; bool flag; + struct ucl_object_userdata *ud; + const char *ud_out = ""; if (ctx->id != UCL_EMIT_CONFIG && !first) { if (compact) { func->ucl_emitter_append_character (',', 1, func->ud); } else { - func->ucl_emitter_append_len (",\n", 2, func->ud); + if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) { + func->ucl_emitter_append_len ("\n", 1, func->ud); + } else { + func->ucl_emitter_append_len (",\n", 2, func->ud); + } } } - ucl_add_tabs (func, ctx->ident, compact); + ucl_add_tabs (func, ctx->indent, compact); switch (obj->type) { case UCL_INT: @@ -379,7 +398,12 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx, break; case UCL_STRING: ucl_emitter_print_key (print_key, ctx, obj, compact); - ucl_elt_string_write_json (obj->value.sv, obj->len, ctx); + if (ctx->id == UCL_EMIT_CONFIG && ucl_maybe_long_string (obj)) { + ucl_elt_string_write_multiline (obj->value.sv, obj->len, ctx); + } + else { + ucl_elt_string_write_json (obj->value.sv, obj->len, ctx); + } ucl_emitter_finish_object (ctx, obj, compact, !print_key); break; case UCL_NULL: @@ -396,6 +420,16 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx, ucl_emitter_common_end_array (ctx, obj, compact); break; case UCL_USERDATA: + ud = (struct ucl_object_userdata *)obj; + ucl_emitter_print_key (print_key, ctx, obj, compact); + if (ud->emitter) { + ud_out = ud->emitter (obj->value.ud); + if (ud_out == NULL) { + ud_out = "null"; + } + } + ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx); + ucl_emitter_finish_object (ctx, obj, compact, !print_key); break; } } @@ -425,10 +459,10 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx, ucl_emitter_common_end_array (ctx, obj, (compact)); \ } -UCL_EMIT_TYPE_IMPL(json, false); -UCL_EMIT_TYPE_IMPL(json_compact, true); -UCL_EMIT_TYPE_IMPL(config, false); -UCL_EMIT_TYPE_IMPL(yaml, false); +UCL_EMIT_TYPE_IMPL(json, false) +UCL_EMIT_TYPE_IMPL(json_compact, true) +UCL_EMIT_TYPE_IMPL(config, false) +UCL_EMIT_TYPE_IMPL(yaml, false) unsigned char * ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type) @@ -461,7 +495,7 @@ ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, if (ctx != NULL) { memcpy (&my_ctx, ctx, sizeof (my_ctx)); my_ctx.func = emitter; - my_ctx.ident = 0; + my_ctx.indent = 0; my_ctx.top = obj; my_ctx.ops->ucl_emitter_write_elt (&my_ctx, obj, true, false); diff --git a/contrib/libucl/src/ucl_emitter_streamline.c b/contrib/libucl/src/ucl_emitter_streamline.c index acf4a305a46e..ff27c88244a5 100644 --- a/contrib/libucl/src/ucl_emitter_streamline.c +++ b/contrib/libucl/src/ucl_emitter_streamline.c @@ -108,9 +108,8 @@ ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx, st->is_array = false; sctx->ops->ucl_emitter_start_object (ctx, obj, print_key); } + LL_PREPEND (sctx->containers, st); } - - LL_PREPEND (sctx->containers, st); } void diff --git a/contrib/libucl/src/ucl_emitter_utils.c b/contrib/libucl/src/ucl_emitter_utils.c index c619ab9df15e..da412097ffbc 100644 --- a/contrib/libucl/src/ucl_emitter_utils.c +++ b/contrib/libucl/src/ucl_emitter_utils.c @@ -93,9 +93,7 @@ ucl_elt_string_write_json (const char *str, size_t size, size_t len = 0; const struct ucl_emitter_functions *func = ctx->func; - if (ctx->id != UCL_EMIT_YAML) { - func->ucl_emitter_append_character ('"', 1, func->ud); - } + func->ucl_emitter_append_character ('"', 1, func->ud); while (size) { if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) { @@ -137,9 +135,18 @@ ucl_elt_string_write_json (const char *str, size_t size, if (len > 0) { func->ucl_emitter_append_len (c, len, func->ud); } - if (ctx->id != UCL_EMIT_YAML) { - func->ucl_emitter_append_character ('"', 1, func->ud); - } + func->ucl_emitter_append_character ('"', 1, func->ud); +} + +void +ucl_elt_string_write_multiline (const char *str, size_t size, + struct ucl_emitter_context *ctx) +{ + const struct ucl_emitter_functions *func = ctx->func; + + func->ucl_emitter_append_len ("<ud); + func->ucl_emitter_append_len (str, size, func->ud); + func->ucl_emitter_append_len ("\nEOD", sizeof ("\nEOD") - 1, func->ud); } /* @@ -154,7 +161,7 @@ ucl_utstring_append_character (unsigned char c, size_t len, void *ud) utstring_append_c (buf, c); } else { - utstring_reserve (buf, len); + utstring_reserve (buf, len + 1); memset (&buf->d[buf->i], c, len); buf->i += len; buf->d[buf->i] = '\0'; @@ -267,19 +274,23 @@ ucl_fd_append_character (unsigned char c, size_t len, void *ud) unsigned char *buf; if (len == 1) { - write (fd, &c, 1); + return write (fd, &c, 1); } else { buf = malloc (len); if (buf == NULL) { /* Fallback */ while (len --) { - write (fd, &c, 1); + if (write (fd, &c, 1) == -1) { + return -1; + } } } else { memset (buf, c, len); - write (fd, buf, len); + if (write (fd, buf, len) == -1) { + return -1; + } free (buf); } } @@ -292,9 +303,7 @@ ucl_fd_append_len (const unsigned char *str, size_t len, void *ud) { int fd = *(int *)ud; - write (fd, str, len); - - return 0; + return write (fd, str, len); } static int @@ -304,9 +313,7 @@ ucl_fd_append_int (int64_t val, void *ud) char intbuf[64]; snprintf (intbuf, sizeof (intbuf), "%jd", (intmax_t)val); - write (fd, intbuf, strlen (intbuf)); - - return 0; + return write (fd, intbuf, strlen (intbuf)); } static int @@ -327,9 +334,7 @@ ucl_fd_append_double (double val, void *ud) snprintf (nbuf, sizeof (nbuf), "%lf", val); } - write (fd, nbuf, strlen (nbuf)); - - return 0; + return write (fd, nbuf, strlen (nbuf)); } struct ucl_emitter_functions* @@ -464,3 +469,18 @@ ucl_object_emit_single_json (const ucl_object_t *obj) return res; } + +#define LONG_STRING_LIMIT 80 + +bool +ucl_maybe_long_string (const ucl_object_t *obj) +{ + if (obj->len > LONG_STRING_LIMIT || (obj->flags & UCL_OBJECT_MULTILINE)) { + /* String is long enough, so search for newline characters in it */ + if (memchr (obj->value.sv, '\n', obj->len) != NULL) { + return true; + } + } + + return false; +} diff --git a/contrib/libucl/src/ucl_hash.c b/contrib/libucl/src/ucl_hash.c index c2e80cb4b252..ea55491ed504 100644 --- a/contrib/libucl/src/ucl_hash.c +++ b/contrib/libucl/src/ucl_hash.c @@ -66,6 +66,20 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node); } +void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old, + const ucl_object_t *new) +{ + ucl_hash_node_t *node; + + HASH_FIND (hh, hashlin->buckets, old->key, old->keylen, node); + if (node != NULL) { + /* Direct replacement */ + node->data = new; + node->hh.key = new->key; + node->hh.keylen = new->keylen; + } +} + const void* ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) { @@ -122,5 +136,6 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj) if (found) { HASH_DELETE (hh, hashlin->buckets, found); + UCL_FREE (sizeof (ucl_hash_node_t), found); } } diff --git a/contrib/libucl/src/ucl_hash.h b/contrib/libucl/src/ucl_hash.h index cbbf005240bd..ddbfdba19ce8 100644 --- a/contrib/libucl/src/ucl_hash.h +++ b/contrib/libucl/src/ucl_hash.h @@ -65,6 +65,12 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func); void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *key, unsigned keylen); +/** + * Replace element in the hash + */ +void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old, + const ucl_object_t *new); + /** * Delete an element from the the hashtable. */ diff --git a/contrib/libucl/src/ucl_internal.h b/contrib/libucl/src/ucl_internal.h index 0ac8de84c2ed..2f75872b7bb8 100644 --- a/contrib/libucl/src/ucl_internal.h +++ b/contrib/libucl/src/ucl_internal.h @@ -163,6 +163,7 @@ struct ucl_chunk { size_t remain; unsigned int line; unsigned int column; + unsigned priority; struct ucl_chunk *next; }; @@ -182,7 +183,7 @@ struct ucl_variable { char *value; size_t var_len; size_t value_len; - struct ucl_variable *next; + struct ucl_variable *prev, *next; }; struct ucl_parser { @@ -192,6 +193,7 @@ struct ucl_parser { int flags; ucl_object_t *top_obj; ucl_object_t *cur_obj; + char *cur_file; struct ucl_macro *macroes; struct ucl_stack *stack; struct ucl_chunk *chunks; @@ -202,6 +204,12 @@ struct ucl_parser { UT_string *err; }; +struct ucl_object_userdata { + ucl_object_t obj; + ucl_userdata_dtor dtor; + ucl_userdata_emitter emitter; +}; + /** * Unescape json string inplace * @param str @@ -216,9 +224,11 @@ size_t ucl_unescape_json_string (char *str, size_t len); * @param err error ptr * @return */ -bool ucl_include_handler (const unsigned char *data, size_t len, void* ud); +bool ucl_include_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud); -bool ucl_try_include_handler (const unsigned char *data, size_t len, void* ud); +bool ucl_try_include_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud); /** * Handle includes macro @@ -228,7 +238,8 @@ bool ucl_try_include_handler (const unsigned char *data, size_t len, void* ud); * @param err error ptr * @return */ -bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud); +bool ucl_includes_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud); size_t ucl_strlcpy (char *dst, const char *src, size_t siz); size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz); @@ -264,7 +275,7 @@ ucl_create_err (UT_string **err, const char *fmt, ...) static inline bool ucl_maybe_parse_boolean (ucl_object_t *obj, const unsigned char *start, size_t len) { - const unsigned char *p = start; + const char *p = (const char *)start; bool ret = false, val = false; if (len == 5) { @@ -351,13 +362,22 @@ const struct ucl_emitter_context * ucl_emit_get_standard_context (enum ucl_emitter emit_type); /** - * Serialise string + * Serialize string as JSON string * @param str string to emit * @param buf target buffer */ void ucl_elt_string_write_json (const char *str, size_t size, struct ucl_emitter_context *ctx); +/** + * Write multiline string using `EOD` as string terminator + * @param str + * @param size + * @param ctx + */ +void ucl_elt_string_write_multiline (const char *str, size_t size, + struct ucl_emitter_context *ctx); + /** * Emit a single object to string * @param obj @@ -365,4 +385,12 @@ void ucl_elt_string_write_json (const char *str, size_t size, */ unsigned char * ucl_object_emit_single_json (const ucl_object_t *obj); +/** + * Check whether a specified string is long and should be likely printed in + * multiline mode + * @param obj + * @return + */ +bool ucl_maybe_long_string (const ucl_object_t *obj); + #endif /* UCL_INTERNAL_H_ */ diff --git a/contrib/libucl/src/ucl_parser.c b/contrib/libucl/src/ucl_parser.c index e51a54b77bc6..0d118d84b75a 100644 --- a/contrib/libucl/src/ucl_parser.c +++ b/contrib/libucl/src/ucl_parser.c @@ -26,8 +26,8 @@ #include "ucl_chartable.h" /** - * @file rcl_parser.c - * The implementation of rcl parser + * @file ucl_parser.c + * The implementation of ucl parser */ struct ucl_parser_saved_state { @@ -56,20 +56,33 @@ struct ucl_parser_saved_state { } while (0) static inline void -ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err) +ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **err) { - if (chunk->pos < chunk->end) { - if (isgraph (*chunk->pos)) { - ucl_create_err (err, "error on line %d at column %d: '%s', character: '%c'", - chunk->line, chunk->column, str, *chunk->pos); - } - else { - ucl_create_err (err, "error on line %d at column %d: '%s', character: '0x%02x'", - chunk->line, chunk->column, str, (int)*chunk->pos); - } + const char *fmt_string, *filename; + struct ucl_chunk *chunk = parser->chunks; + + if (parser->cur_file) { + filename = parser->cur_file; } else { - ucl_create_err (err, "error at the end of chunk: %s", str); + filename = ""; + } + if (chunk->pos < chunk->end) { + if (isgraph (*chunk->pos)) { + fmt_string = "error while parsing %s: " + "line: %d, column: %d - '%s', character: '%c'"; + } + else { + fmt_string = "error while parsing %s: " + "line: %d, column: %d - '%s', character: '0x%02x'"; + } + ucl_create_err (err, fmt_string, + filename, chunk->line, chunk->column, + str, *chunk->pos); + } + else { + ucl_create_err (err, "error while parsing %s: at the end of chunk: %s", + filename, str); } } @@ -84,11 +97,12 @@ ucl_skip_comments (struct ucl_parser *parser) struct ucl_chunk *chunk = parser->chunks; const unsigned char *p; int comments_nested = 0; + bool quoted = false; p = chunk->pos; start: - if (*p == '#') { + if (chunk->remain > 0 && *p == '#') { if (parser->state != UCL_STATE_SCOMMENT && parser->state != UCL_STATE_MCOMMENT) { while (p < chunk->end) { @@ -100,34 +114,41 @@ ucl_skip_comments (struct ucl_parser *parser) } } } - else if (*p == '/' && chunk->remain >= 2) { + else if (chunk->remain >= 2 && *p == '/') { if (p[1] == '*') { ucl_chunk_skipc (chunk, p); comments_nested ++; ucl_chunk_skipc (chunk, p); while (p < chunk->end) { - if (*p == '*') { - ucl_chunk_skipc (chunk, p); - if (*p == '/') { - comments_nested --; - if (comments_nested == 0) { - ucl_chunk_skipc (chunk, p); - goto start; - } - } - ucl_chunk_skipc (chunk, p); + if (*p == '"' && *(p - 1) != '\\') { + quoted = !quoted; } - else if (p[0] == '/' && chunk->remain >= 2 && p[1] == '*') { - comments_nested ++; - ucl_chunk_skipc (chunk, p); - ucl_chunk_skipc (chunk, p); - continue; + + if (!quoted) { + if (*p == '*') { + ucl_chunk_skipc (chunk, p); + if (*p == '/') { + comments_nested --; + if (comments_nested == 0) { + ucl_chunk_skipc (chunk, p); + goto start; + } + } + ucl_chunk_skipc (chunk, p); + } + else if (p[0] == '/' && chunk->remain >= 2 && p[1] == '*') { + comments_nested ++; + ucl_chunk_skipc (chunk, p); + ucl_chunk_skipc (chunk, p); + continue; + } } ucl_chunk_skipc (chunk, p); } if (comments_nested != 0) { - ucl_set_err (chunk, UCL_ENESTED, "unfinished multiline comment", &parser->err); + ucl_set_err (parser, UCL_ENESTED, + "unfinished multiline comment", &parser->err); return false; } } @@ -492,7 +513,8 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser, /* Copy string */ *dst = UCL_ALLOC (in_len + 1); if (*dst == NULL) { - ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", &parser->err); + ucl_set_err (parser, 0, "cannot allocate memory for a string", + &parser->err); return false; } if (need_lowercase) { @@ -514,6 +536,10 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser, *dst = tmp; ret = tret; } + else { + /* Free unexpanded value */ + UCL_FREE (in_len + 1, tmp); + } } *dst_const = *dst; } @@ -539,7 +565,7 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra if (!is_array) { if (obj == NULL) { - obj = ucl_object_typed_new (UCL_OBJECT); + obj = ucl_object_new_full (UCL_OBJECT, parser->chunks->priority); } else { obj->type = UCL_OBJECT; @@ -549,7 +575,7 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra } else { if (obj == NULL) { - obj = ucl_object_typed_new (UCL_ARRAY); + obj = ucl_object_new_full (UCL_ARRAY, parser->chunks->priority); } else { obj->type = UCL_ARRAY; @@ -559,7 +585,9 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra st = UCL_ALLOC (sizeof (struct ucl_stack)); if (st == NULL) { - ucl_set_err (parser->chunks, 0, "cannot allocate memory for an object", &parser->err); + ucl_set_err (parser, 0, "cannot allocate memory for an object", + &parser->err); + ucl_object_unref (obj); return NULL; } st->obj = obj; @@ -676,8 +704,7 @@ ucl_maybe_parse_number (ucl_object_t *obj, } /* Now check endptr */ - if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0' || - ucl_test_character (*endptr, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') { p = endptr; goto set_obj; } @@ -788,8 +815,21 @@ ucl_maybe_parse_number (ucl_object_t *obj, goto set_obj; } break; + case '\t': + case ' ': + while (p < end && ucl_test_character(*p, UCL_CHARACTER_WHITESPACE)) { + p++; + } + if (ucl_lex_is_atom_end(*p)) + goto set_obj; + break; } } + else if (endptr == end) { + /* Just a number at the end of chunk */ + p = endptr; + goto set_obj; + } *pos = c; return EINVAL; @@ -835,7 +875,7 @@ ucl_lex_number (struct ucl_parser *parser, return true; } else if (ret == ERANGE) { - ucl_set_err (chunk, ERANGE, "numeric value out of range", &parser->err); + ucl_set_err (parser, ERANGE, "numeric value out of range", &parser->err); } return false; @@ -860,10 +900,12 @@ ucl_lex_json_string (struct ucl_parser *parser, if (c < 0x1F) { /* Unmasked control character */ if (c == '\n') { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unexpected newline", + &parser->err); } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unexpected control character", + &parser->err); } return false; } @@ -871,7 +913,8 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); c = *p; if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character", + &parser->err); return false; } else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) { @@ -879,13 +922,15 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); for (i = 0; i < 4 && p < chunk->end; i ++) { if (!isxdigit (*p)) { - ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "invalid utf escape", + &parser->err); return false; } ucl_chunk_skipc (chunk, p); } if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character", + &parser->err); return false; } } @@ -910,10 +955,42 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); } - ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "no quote at the end of json string", + &parser->err); return false; } +static void +ucl_parser_append_elt (struct ucl_parser *parser, ucl_hash_t *cont, + ucl_object_t *top, + ucl_object_t *elt) +{ + ucl_object_t *nobj; + + if ((parser->flags & UCL_PARSER_NO_IMPLICIT_ARRAYS) == 0) { + /* Implicit array */ + top->flags |= UCL_OBJECT_MULTIVALUE; + DL_APPEND (top, elt); + } + else { + if ((top->flags & UCL_OBJECT_MULTIVALUE) != 0) { + /* Just add to the explicit array */ + DL_APPEND (top->value.av, elt); + } + else { + /* Convert to an array */ + ucl_hash_delete (cont, top); + nobj = ucl_object_typed_new (UCL_ARRAY); + nobj->key = top->key; + nobj->keylen = top->keylen; + nobj->flags |= UCL_OBJECT_MULTIVALUE; + DL_APPEND (nobj->value.av, top); + DL_APPEND (nobj->value.av, elt); + ucl_hash_insert (cont, nobj, nobj->key, nobj->keylen); + } + } +} + /** * Parse a key in an object * @param parser @@ -981,7 +1058,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke } else { /* Invalid identifier */ - ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "key must begin with a letter", + &parser->err); return false; } } @@ -997,7 +1075,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke break; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "invalid character in a key", + &parser->err); return false; } } @@ -1015,7 +1094,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke } if (p >= chunk->end && got_content) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } else if (!got_content) { @@ -1033,7 +1112,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke got_eq = true; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unexpected '=' character", + &parser->err); return false; } } @@ -1043,7 +1123,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke got_semicolon = true; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unexpected ':' character", + &parser->err); return false; } } @@ -1061,7 +1142,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke } if (p >= chunk->end && got_content) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } @@ -1096,7 +1177,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke } /* Create a new object */ - nobj = ucl_object_new (); + nobj = ucl_object_new_full (UCL_NULL, parser->chunks->priority); keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], &key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false); if (keylen == -1) { @@ -1104,7 +1185,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke return false; } else if (keylen == 0) { - ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "empty keys are not allowed", &parser->err); ucl_object_unref (nobj); return false; } @@ -1120,7 +1201,27 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke parser->stack->obj->len ++; } else { - DL_APPEND (tobj, nobj); + /* + * The logic here is the following: + * + * - if we have two objects with the same priority, then we form an + * implicit or explicit array + * - if a new object has bigger priority, then we overwrite an old one + * - if a new object has lower priority, then we ignore it + */ + unsigned priold = ucl_object_get_priority (tobj), + prinew = ucl_object_get_priority (nobj); + if (priold == prinew) { + ucl_parser_append_elt (parser, container, tobj, nobj); + } + else if (priold > prinew) { + ucl_object_unref (nobj); + return true; + } + else { + ucl_hash_replace (container, tobj, nobj); + ucl_object_unref (tobj); + } } if (ucl_escape) { @@ -1197,11 +1298,6 @@ ucl_parse_string_value (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); } - if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", &parser->err); - return false; - } - return true; } @@ -1219,7 +1315,7 @@ ucl_parse_multiline_string (struct ucl_parser *parser, int term_len, unsigned char const **beg, bool *var_expand) { - const unsigned char *p, *c; + const unsigned char *p, *c, *tend; bool newline = false; int len = 0; @@ -1232,7 +1328,13 @@ ucl_parse_multiline_string (struct ucl_parser *parser, if (chunk->end - p < term_len) { return 0; } - else if (memcmp (p, term, term_len) == 0 && (p[term_len] == '\n' || p[term_len] == '\r')) { + else if (memcmp (p, term, term_len) == 0) { + tend = p + term_len; + if (*tend != '\n' && *tend != ';' && *tend != ',') { + /* Incomplete terminator */ + ucl_chunk_skipc (chunk, p); + continue; + } len = p - c; chunk->remain -= term_len; chunk->pos = p + term_len; @@ -1263,7 +1365,7 @@ ucl_get_value_object (struct ucl_parser *parser) if (parser->stack->obj->type == UCL_ARRAY) { /* Object must be allocated */ - obj = ucl_object_new (); + obj = ucl_object_new_full (UCL_NULL, parser->chunks->priority); t = parser->stack->obj->value.av; DL_APPEND (t, obj); parser->cur_obj = obj; @@ -1378,7 +1480,8 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) chunk->line ++; if ((str_len = ucl_parse_multiline_string (parser, chunk, c, p - c, &c, &var_expand)) == 0) { - ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, + "unterminated multiline value", &parser->err); return false; } obj->type = UCL_STRING; @@ -1423,7 +1526,8 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) } str_len = chunk->pos - c - stripped_spaces; if (str_len <= 0) { - ucl_set_err (chunk, 0, "string value must not be empty", &parser->err); + ucl_set_err (parser, 0, "string value must not be empty", + &parser->err); return false; } else if (str_len == 4 && memcmp (c, "null", 4) == 0) { @@ -1482,7 +1586,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) { if (*p == '}' || *p == ']') { if (parser->stack == NULL) { - ucl_set_err (chunk, UCL_ESYNTAX, "end of array or object detected without corresponding start", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, + "end of array or object detected without corresponding start", + &parser->err); return false; } if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) || @@ -1503,7 +1609,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) } } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, + "unexpected terminating symbol detected", + &parser->err); return false; } @@ -1525,7 +1633,8 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) else { /* Anything else */ if (!got_sep) { - ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", &parser->err); + ucl_set_err (parser, UCL_ESYNTAX, "delimiter is missing", + &parser->err); return false; } return true; @@ -1612,6 +1721,120 @@ ucl_parse_macro_value (struct ucl_parser *parser, return true; } +/** + * Parse macro arguments as UCL object + * @param parser parser structure + * @param chunk the current data chunk + * @return + */ +static ucl_object_t * +ucl_parse_macro_arguments (struct ucl_parser *parser, + struct ucl_chunk *chunk) +{ + ucl_object_t *res = NULL; + struct ucl_parser *params_parser; + int obraces = 1, ebraces = 0, state = 0; + const unsigned char *p, *c; + size_t args_len = 0; + struct ucl_parser_saved_state saved; + + saved.column = chunk->column; + saved.line = chunk->line; + saved.pos = chunk->pos; + saved.remain = chunk->remain; + p = chunk->pos; + + if (*p != '(' || chunk->remain < 2) { + return NULL; + } + + /* Set begin and start */ + ucl_chunk_skipc (chunk, p); + c = p; + + while ((p) < (chunk)->end) { + switch (state) { + case 0: + /* Parse symbols and check for '(', ')' and '"' */ + if (*p == '(') { + obraces ++; + } + else if (*p == ')') { + ebraces ++; + } + else if (*p == '"') { + state = 1; + } + /* Check pairing */ + if (obraces == ebraces) { + state = 99; + } + else { + args_len ++; + } + /* Check overflow */ + if (chunk->remain == 0) { + goto restore_chunk; + } + ucl_chunk_skipc (chunk, p); + break; + case 1: + /* We have quote character, so skip all but quotes */ + if (*p == '"' && *(p - 1) != '\\') { + state = 0; + } + if (chunk->remain == 0) { + goto restore_chunk; + } + ucl_chunk_skipc (chunk, p); + break; + case 99: + /* + * We have read the full body of arguments, so we need to parse and set + * object from that + */ + params_parser = ucl_parser_new (parser->flags); + if (!ucl_parser_add_chunk (params_parser, c, args_len)) { + ucl_set_err (parser, UCL_ESYNTAX, "macro arguments parsing error", + &parser->err); + } + else { + res = ucl_parser_get_object (params_parser); + } + ucl_parser_free (params_parser); + + return res; + + break; + } + } + + return res; + +restore_chunk: + chunk->column = saved.column; + chunk->line = saved.line; + chunk->pos = saved.pos; + chunk->remain = saved.remain; + + return NULL; +} + +#define SKIP_SPACES_COMMENTS(parser, chunk, p) do { \ + while ((p) < (chunk)->end) { \ + if (!ucl_test_character (*(p), UCL_CHARACTER_WHITESPACE_UNSAFE)) { \ + if ((chunk)->remain >= 2 && ucl_lex_is_comment ((p)[0], (p)[1])) { \ + if (!ucl_skip_comments (parser)) { \ + return false; \ + } \ + p = (chunk)->pos; \ + } \ + break; \ + } \ + ucl_chunk_skipc (chunk, p); \ + } \ +} while(0) + /** * Handle the main states of rcl parser * @param parser parser structure @@ -1622,13 +1845,13 @@ ucl_parse_macro_value (struct ucl_parser *parser, static bool ucl_state_machine (struct ucl_parser *parser) { - ucl_object_t *obj; + ucl_object_t *obj, *macro_args; struct ucl_chunk *chunk = parser->chunks; const unsigned char *p, *c = NULL, *macro_start = NULL; unsigned char *macro_escaped; size_t macro_len = 0; struct ucl_macro *macro = NULL; - bool next_key = false, end_of_object = false; + bool next_key = false, end_of_object = false, ret; if (parser->top_obj == NULL) { if (*chunk->pos == '[') { @@ -1654,7 +1877,6 @@ ucl_state_machine (struct ucl_parser *parser) * if we got [ or { correspondingly or can just treat new data as * a key of newly created object */ - obj = parser->cur_obj; if (!ucl_skip_comments (parser)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; @@ -1691,7 +1913,7 @@ ucl_state_machine (struct ucl_parser *parser) } if (parser->stack == NULL) { /* No objects are on stack, but we want to parse a key */ - ucl_set_err (chunk, UCL_ESYNTAX, "top object is finished but the parser " + ucl_set_err (parser, UCL_ESYNTAX, "top object is finished but the parser " "expects a key", &parser->err); parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; @@ -1757,7 +1979,8 @@ ucl_state_machine (struct ucl_parser *parser) p = chunk->pos; break; case UCL_STATE_MACRO_NAME: - if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { + if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE) && + *p != '(') { ucl_chunk_skipc (chunk, p); } else if (p - c > 0) { @@ -1772,48 +1995,51 @@ ucl_state_machine (struct ucl_parser *parser) return false; } /* Now we need to skip all spaces */ - while (p < chunk->end) { - if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { - if (chunk->remain >= 2 && ucl_lex_is_comment (p[0], p[1])) { - /* Skip comment */ - if (!ucl_skip_comments (parser)) { - return false; - } - p = chunk->pos; - } - break; - } - ucl_chunk_skipc (chunk, p); - } + SKIP_SPACES_COMMENTS(parser, chunk, p); parser->state = UCL_STATE_MACRO; } break; case UCL_STATE_MACRO: + if (*chunk->pos == '(') { + macro_args = ucl_parse_macro_arguments (parser, chunk); + p = chunk->pos; + if (macro_args) { + SKIP_SPACES_COMMENTS(parser, chunk, p); + } + } + else { + macro_args = NULL; + } if (!ucl_parse_macro_value (parser, chunk, macro, ¯o_start, ¯o_len)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; } - macro_len = ucl_expand_variable (parser, ¯o_escaped, macro_start, macro_len); + macro_len = ucl_expand_variable (parser, ¯o_escaped, + macro_start, macro_len); parser->state = parser->prev_state; if (macro_escaped == NULL) { - if (!macro->handler (macro_start, macro_len, macro->ud)) { - return false; - } + ret = macro->handler (macro_start, macro_len, macro_args, + macro->ud); } else { - if (!macro->handler (macro_escaped, macro_len, macro->ud)) { - UCL_FREE (macro_len + 1, macro_escaped); - return false; - } + ret = macro->handler (macro_escaped, macro_len, macro_args, + macro->ud); UCL_FREE (macro_len + 1, macro_escaped); } p = chunk->pos; + if (macro_args) { + ucl_object_unref (macro_args); + } + if (!ret) { + return false; + } break; default: /* TODO: add all states */ - ucl_set_err (chunk, UCL_EINTERNAL, "internal error: parser is in an unknown state", &parser->err); + ucl_set_err (parser, UCL_EINTERNAL, + "internal error: parser is in an unknown state", &parser->err); parser->state = UCL_STATE_ERROR; return false; } @@ -1888,7 +2114,7 @@ ucl_parser_register_variable (struct ucl_parser *parser, const char *var, if (new != NULL) { /* Remove variable */ - LL_DELETE (parser->variables, new); + DL_DELETE (parser->variables, new); free (new->var); free (new->value); UCL_FREE (sizeof (struct ucl_variable), new); @@ -1910,7 +2136,7 @@ ucl_parser_register_variable (struct ucl_parser *parser, const char *var, new->value = strdup (value); new->value_len = strlen (value); - LL_PREPEND (parser->variables, new); + DL_APPEND (parser->variables, new); } else { free (new->value); @@ -1929,15 +2155,19 @@ ucl_parser_set_variables_handler (struct ucl_parser *parser, } bool -ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, - size_t len) +ucl_parser_add_chunk_priority (struct ucl_parser *parser, const unsigned char *data, + size_t len, unsigned priority) { struct ucl_chunk *chunk; - if (data == NULL || len == 0) { + if (data == NULL) { ucl_create_err (&parser->err, "invalid chunk added"); return false; } + if (len == 0) { + parser->top_obj = ucl_object_new_full (UCL_OBJECT, priority); + return true; + } if (parser->state != UCL_STATE_ERROR) { chunk = UCL_ALLOC (sizeof (struct ucl_chunk)); if (chunk == NULL) { @@ -1950,6 +2180,7 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, chunk->end = chunk->begin + len; chunk->line = 1; chunk->column = 0; + chunk->priority = priority; LL_PREPEND (parser->chunks, chunk); parser->recursion ++; if (parser->recursion > UCL_MAX_RECURSION) { @@ -1965,6 +2196,13 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, return false; } +bool +ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, + size_t len) +{ + return ucl_parser_add_chunk_priority (parser, data, len, 0); +} + bool ucl_parser_add_string (struct ucl_parser *parser, const char *data, size_t len) diff --git a/contrib/libucl/src/ucl_util.c b/contrib/libucl/src/ucl_util.c index 63f5e629826f..41702e941f5b 100644 --- a/contrib/libucl/src/ucl_util.c +++ b/contrib/libucl/src/ucl_util.c @@ -25,6 +25,8 @@ #include "ucl_internal.h" #include "ucl_chartable.h" +#include + #ifdef HAVE_LIBGEN_H #include /* For dirname */ #endif @@ -129,11 +131,6 @@ static char* ucl_realpath(const char *path, char *resolved_path) { #define ucl_realpath realpath #endif -/** - * @file rcl_util.c - * Utilities for rcl parsing - */ - typedef void (*ucl_object_dtor) (ucl_object_t *obj); static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor); @@ -148,7 +145,19 @@ ucl_object_dtor_free (ucl_object_t *obj) if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) { UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]); } - UCL_FREE (sizeof (ucl_object_t), obj); + /* Do not free ephemeral objects */ + if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) { + if (obj->type != UCL_USERDATA) { + UCL_FREE (sizeof (ucl_object_t), obj); + } + else { + struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj; + if (ud->dtor) { + ud->dtor (obj->value.ud); + } + UCL_FREE (sizeof (*ud), obj); + } + } } /* @@ -423,7 +432,11 @@ ucl_parser_free (struct ucl_parser *parser) } if (parser->err != NULL) { - utstring_free(parser->err); + utstring_free (parser->err); + } + + if (parser->cur_file) { + free (parser->cur_file); } UCL_FREE (sizeof (struct ucl_parser), parser); @@ -701,7 +714,8 @@ ucl_sig_check (const unsigned char *data, size_t datalen, */ static bool ucl_include_url (const unsigned char *data, size_t len, - struct ucl_parser *parser, bool check_signature, bool must_exist) + struct ucl_parser *parser, bool check_signature, bool must_exist, + unsigned priority) { bool res; @@ -744,7 +758,7 @@ ucl_include_url (const unsigned char *data, size_t len, prev_state = parser->state; parser->state = UCL_STATE_INIT; - res = ucl_parser_add_chunk (parser, buf, buflen); + res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority); if (res == true) { /* Remove chunk from the stack */ chunk = parser->chunks; @@ -761,23 +775,30 @@ ucl_include_url (const unsigned char *data, size_t len, } /** - * Include a file to configuration + * Include a single file to the parser * @param data * @param len * @param parser - * @param err + * @param check_signature + * @param must_exist + * @param allow_glob + * @param priority * @return */ static bool -ucl_include_file (const unsigned char *data, size_t len, - struct ucl_parser *parser, bool check_signature, bool must_exist) +ucl_include_file_single (const unsigned char *data, size_t len, + struct ucl_parser *parser, bool check_signature, bool must_exist, + unsigned priority) { bool res; struct ucl_chunk *chunk; unsigned char *buf = NULL; + char *old_curfile; size_t buflen; char filebuf[PATH_MAX], realbuf[PATH_MAX]; int prev_state; + struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL, + *old_filename = NULL; snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); if (ucl_realpath (filebuf, realbuf) == NULL) { @@ -790,6 +811,13 @@ ucl_include_file (const unsigned char *data, size_t len, return false; } + if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) { + /* We are likely including the file itself */ + ucl_create_err (&parser->err, "trying to include the file %s from itself", + realbuf); + return false; + } + if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) { return (!must_exist || false); } @@ -818,19 +846,66 @@ ucl_include_file (const unsigned char *data, size_t len, #endif } + old_curfile = parser->cur_file; + parser->cur_file = strdup (realbuf); + + /* Store old file vars */ + DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { + if (strcmp (cur_var->var, "CURDIR") == 0) { + old_curdir = cur_var; + DL_DELETE (parser->variables, cur_var); + } + else if (strcmp (cur_var->var, "FILENAME") == 0) { + old_filename = cur_var; + DL_DELETE (parser->variables, cur_var); + } + } + ucl_parser_set_filevars (parser, realbuf, false); prev_state = parser->state; parser->state = UCL_STATE_INIT; - res = ucl_parser_add_chunk (parser, buf, buflen); - if (res == true) { - /* Remove chunk from the stack */ - chunk = parser->chunks; - if (chunk != NULL) { - parser->chunks = chunk->next; - UCL_FREE (sizeof (struct ucl_chunk), chunk); + res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority); + if (!res && !must_exist) { + /* Free error */ + utstring_free (parser->err); + parser->err = NULL; + parser->state = UCL_STATE_AFTER_VALUE; + } + + /* Remove chunk from the stack */ + chunk = parser->chunks; + if (chunk != NULL) { + parser->chunks = chunk->next; + UCL_FREE (sizeof (struct ucl_chunk), chunk); + parser->recursion --; + } + + /* Restore old file vars */ + parser->cur_file = old_curfile; + DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) { + if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) { + DL_DELETE (parser->variables, cur_var); + free (cur_var->var); + free (cur_var->value); + UCL_FREE (sizeof (struct ucl_variable), cur_var); } + else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) { + DL_DELETE (parser->variables, cur_var); + free (cur_var->var); + free (cur_var->value); + UCL_FREE (sizeof (struct ucl_variable), cur_var); + } + } + if (old_filename) { + DL_APPEND (parser->variables, old_filename); + } + if (old_curdir) { + DL_APPEND (parser->variables, old_curdir); + } + if (old_curfile) { + free (old_curfile); } parser->state = prev_state; @@ -842,6 +917,138 @@ ucl_include_file (const unsigned char *data, size_t len, return res; } +/** + * Include a file to configuration + * @param data + * @param len + * @param parser + * @param err + * @return + */ +static bool +ucl_include_file (const unsigned char *data, size_t len, + struct ucl_parser *parser, bool check_signature, bool must_exist, + bool allow_glob, unsigned priority) +{ + const unsigned char *p = data, *end = data + len; + bool need_glob = false; + int cnt = 0; + glob_t globbuf; + char glob_pattern[PATH_MAX]; + size_t i; + + if (!allow_glob) { + return ucl_include_file_single (data, len, parser, check_signature, + must_exist, priority); + } + else { + /* Check for special symbols in a filename */ + while (p != end) { + if (*p == '*' || *p == '?') { + need_glob = true; + break; + } + p ++; + } + if (need_glob) { + memset (&globbuf, 0, sizeof (globbuf)); + ucl_strlcpy (glob_pattern, (const char *)data, sizeof (glob_pattern)); + if (glob (glob_pattern, 0, NULL, &globbuf) != 0) { + return (!must_exist || false); + } + for (i = 0; i < globbuf.gl_pathc; i ++) { + if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i], + strlen (globbuf.gl_pathv[i]), parser, check_signature, + must_exist, priority)) { + globfree (&globbuf); + return false; + } + cnt ++; + } + globfree (&globbuf); + + if (cnt == 0 && must_exist) { + ucl_create_err (&parser->err, "cannot match any files for pattern %s", + glob_pattern); + return false; + } + } + else { + return ucl_include_file_single (data, len, parser, check_signature, + must_exist, priority); + } + } + + return true; +} + +/** + * Common function to handle .*include* macros + * @param data + * @param len + * @param args + * @param parser + * @param default_try + * @param default_sign + * @return + */ +static bool +ucl_include_common (const unsigned char *data, size_t len, + const ucl_object_t *args, struct ucl_parser *parser, + bool default_try, + bool default_sign) +{ + bool try_load, allow_glob, allow_url, need_sign; + unsigned priority; + const ucl_object_t *param; + ucl_object_iter_t it = NULL; + + /* Default values */ + try_load = default_try; + allow_glob = false; + allow_url = true; + need_sign = default_sign; + priority = 0; + + /* Process arguments */ + if (args != NULL && args->type == UCL_OBJECT) { + while ((param = ucl_iterate_object (args, &it, true)) != NULL) { + if (param->type == UCL_BOOLEAN) { + if (strcmp (param->key, "try") == 0) { + try_load = ucl_object_toboolean (param); + } + else if (strcmp (param->key, "sign") == 0) { + need_sign = ucl_object_toboolean (param); + } + else if (strcmp (param->key, "glob") == 0) { + allow_glob = ucl_object_toboolean (param); + } + else if (strcmp (param->key, "url") == 0) { + allow_url = ucl_object_toboolean (param); + } + } + else if (param->type == UCL_INT) { + if (strcmp (param->key, "priority") == 0) { + priority = ucl_object_toint (param); + } + } + } + } + + if (*data == '/' || *data == '.') { + /* Try to load a file */ + return ucl_include_file (data, len, parser, need_sign, !try_load, + allow_glob, priority); + } + else if (allow_url) { + /* Globbing is not used for URL's */ + return ucl_include_url (data, len, parser, need_sign, !try_load, + priority); + } + + return false; +} + /** * Handle include macro * @param data include data @@ -851,16 +1058,12 @@ ucl_include_file (const unsigned char *data, size_t len, * @return */ UCL_EXTERN bool -ucl_include_handler (const unsigned char *data, size_t len, void* ud) +ucl_include_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud) { struct ucl_parser *parser = ud; - if (*data == '/' || *data == '.') { - /* Try to load a file */ - return ucl_include_file (data, len, parser, false, true); - } - - return ucl_include_url (data, len, parser, false, true); + return ucl_include_common (data, len, args, parser, false, false); } /** @@ -872,30 +1075,22 @@ ucl_include_handler (const unsigned char *data, size_t len, void* ud) * @return */ UCL_EXTERN bool -ucl_includes_handler (const unsigned char *data, size_t len, void* ud) +ucl_includes_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud) { struct ucl_parser *parser = ud; - if (*data == '/' || *data == '.') { - /* Try to load a file */ - return ucl_include_file (data, len, parser, true, true); - } - - return ucl_include_url (data, len, parser, true, true); + return ucl_include_common (data, len, args, parser, false, true); } UCL_EXTERN bool -ucl_try_include_handler (const unsigned char *data, size_t len, void* ud) +ucl_try_include_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, void* ud) { struct ucl_parser *parser = ud; - if (*data == '/' || *data == '.') { - /* Try to load a file */ - return ucl_include_file (data, len, parser, false, false); - } - - return ucl_include_url (data, len, parser, false, false); + return ucl_include_common (data, len, args, parser, true, false); } UCL_EXTERN bool @@ -947,6 +1142,10 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename) return false; } + if (parser->cur_file) { + free (parser->cur_file); + } + parser->cur_file = strdup (realbuf); ucl_parser_set_filevars (parser, realbuf, false); ret = ucl_parser_add_chunk (parser, buf, len); @@ -957,6 +1156,39 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename) return ret; } +UCL_EXTERN bool +ucl_parser_add_fd (struct ucl_parser *parser, int fd) +{ + unsigned char *buf; + size_t len; + bool ret; + struct stat st; + + if (fstat (fd, &st) == -1) { + ucl_create_err (&parser->err, "cannot stat fd %d: %s", + fd, strerror (errno)); + return false; + } + if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + ucl_create_err (&parser->err, "cannot mmap fd %d: %s", + fd, strerror (errno)); + return false; + } + + if (parser->cur_file) { + free (parser->cur_file); + } + parser->cur_file = NULL; + len = st.st_size; + ret = ucl_parser_add_chunk (parser, buf, len); + + if (len > 0) { + ucl_munmap (buf, len); + } + + return ret; +} + size_t ucl_strlcpy (char *dst, const char *src, size_t siz) { @@ -1176,6 +1408,15 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, } } + /* workaround for some use cases */ + if (elt->trash_stack[UCL_TRASH_KEY] != NULL && + key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) { + /* Remove copied key */ + free (elt->trash_stack[UCL_TRASH_KEY]); + elt->trash_stack[UCL_TRASH_KEY] = NULL; + elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY; + } + elt->key = key; elt->keylen = keylen; @@ -1185,9 +1426,8 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt)); - if (!found) { + if (found == NULL) { top->value.ov = ucl_hash_insert_object (top->value.ov, elt); - DL_APPEND (found, elt); top->len ++; if (replace) { ret = false; @@ -1195,11 +1435,8 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, } else { if (replace) { - ucl_hash_delete (top->value.ov, found); + ucl_hash_replace (top->value.ov, found, elt); ucl_object_unref (found); - top->value.ov = ucl_hash_insert_object (top->value.ov, elt); - found = NULL; - DL_APPEND (found, elt); } else if (merge) { if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { @@ -1310,6 +1547,40 @@ ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true); } +bool +ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) +{ + ucl_object_t *cur = NULL, *cp = NULL, *found = NULL; + ucl_object_iter_t iter = NULL; + + if (top == NULL || top->type != UCL_OBJECT || elt == NULL || elt->type != UCL_OBJECT) { + return false; + } + + /* Mix two hashes */ + while ((cur = (ucl_object_t*)ucl_hash_iterate (elt->value.ov, &iter))) { + if (copy) { + cp = ucl_object_copy (cur); + } + else { + cp = ucl_object_ref (cur); + } + found = __DECONST(ucl_object_t *, ucl_hash_search (top->value.ov, cp->key, cp->keylen)); + if (found == NULL) { + /* The key does not exist */ + top->value.ov = ucl_hash_insert_object (top->value.ov, cp); + top->len ++; + } + else { + /* The key already exists, replace it */ + ucl_hash_replace (top->value.ov, found, cp); + ucl_object_unref (found); + } + } + + return true; +} + const ucl_object_t * ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen) { @@ -1372,9 +1643,6 @@ ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expan elt = *iter; if (elt == NULL) { elt = obj; - if (elt == NULL) { - return NULL; - } } else if (elt == obj) { return NULL; @@ -1442,29 +1710,59 @@ ucl_lookup_path (const ucl_object_t *top, const char *path_in) { ucl_object_t * ucl_object_new (void) { - ucl_object_t *new; - new = malloc (sizeof (ucl_object_t)); - if (new != NULL) { - memset (new, 0, sizeof (ucl_object_t)); - new->ref = 1; - new->type = UCL_NULL; - } - return new; + return ucl_object_typed_new (UCL_NULL); } ucl_object_t * ucl_object_typed_new (ucl_type_t type) +{ + return ucl_object_new_full (type, 0); +} + +ucl_object_t * +ucl_object_new_full (ucl_type_t type, unsigned priority) { ucl_object_t *new; - new = malloc (sizeof (ucl_object_t)); - if (new != NULL) { - memset (new, 0, sizeof (ucl_object_t)); - new->ref = 1; - new->type = (type <= UCL_NULL ? type : UCL_NULL); + + if (type != UCL_USERDATA) { + new = UCL_ALLOC (sizeof (ucl_object_t)); + if (new != NULL) { + memset (new, 0, sizeof (ucl_object_t)); + new->ref = 1; + new->type = (type <= UCL_NULL ? type : UCL_NULL); + new->next = NULL; + new->prev = new; + ucl_object_set_priority (new, priority); + } } + else { + new = ucl_object_new_userdata (NULL, NULL); + ucl_object_set_priority (new, priority); + } + return new; } +ucl_object_t* +ucl_object_new_userdata (ucl_userdata_dtor dtor, ucl_userdata_emitter emitter) +{ + struct ucl_object_userdata *new; + size_t nsize = sizeof (*new); + + new = UCL_ALLOC (nsize); + if (new != NULL) { + memset (new, 0, nsize); + new->obj.ref = 1; + new->obj.type = UCL_USERDATA; + new->obj.next = NULL; + new->obj.prev = (ucl_object_t *)new; + new->dtor = dtor; + new->emitter = emitter; + } + + return (ucl_object_t *)new; +} + ucl_type_t ucl_object_type (const ucl_object_t *obj) { @@ -1576,6 +1874,30 @@ ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) return true; } +bool +ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy) +{ + ucl_object_t *cur, *tmp, *cp; + + if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) { + return false; + } + + DL_FOREACH_SAFE (elt->value.av, cur, tmp) { + if (copy) { + cp = ucl_object_copy (cur); + } + else { + cp = ucl_object_ref (cur); + } + if (cp != NULL) { + ucl_array_append (top, cp); + } + } + + return true; +} + ucl_object_t * ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) { @@ -1660,6 +1982,28 @@ ucl_array_find_index (const ucl_object_t *top, unsigned int index) return NULL; } +ucl_object_t * +ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt, + unsigned int index) +{ + ucl_object_t *cur, *tmp; + + if (top == NULL || top->type != UCL_ARRAY || elt == NULL || + top->len == 0 || (index + 1) > top->len) { + return NULL; + } + + DL_FOREACH_SAFE (top->value.av, cur, tmp) { + if (index == 0) { + DL_REPLACE_ELEM (top->value.av, cur, elt); + return cur; + } + --index; + } + + return NULL; +} + ucl_object_t * ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) { @@ -1849,16 +2193,99 @@ ucl_object_ref (const ucl_object_t *obj) ucl_object_t *res = NULL; if (obj != NULL) { - res = __DECONST (ucl_object_t *, obj); + if (obj->flags & UCL_OBJECT_EPHEMERAL) { + /* + * Use deep copy for ephemeral objects, note that its refcount + * is NOT increased, since ephemeral objects does not need refcount + * at all + */ + res = ucl_object_copy (obj); + } + else { + res = __DECONST (ucl_object_t *, obj); #ifdef HAVE_ATOMIC_BUILTINS - (void)__sync_add_and_fetch (&res->ref, 1); + (void)__sync_add_and_fetch (&res->ref, 1); #else - res->ref ++; + res->ref ++; #endif + } } return res; } +static ucl_object_t * +ucl_object_copy_internal (const ucl_object_t *other, bool allow_array) +{ + + ucl_object_t *new; + ucl_object_iter_t it = NULL; + const ucl_object_t *cur; + + new = malloc (sizeof (*new)); + + if (new != NULL) { + memcpy (new, other, sizeof (*new)); + if (other->flags & UCL_OBJECT_EPHEMERAL) { + /* Copied object is always non ephemeral */ + new->flags &= ~UCL_OBJECT_EPHEMERAL; + } + new->ref = 1; + /* Unlink from others */ + new->next = NULL; + new->prev = new; + + /* deep copy of values stored */ + if (other->trash_stack[UCL_TRASH_KEY] != NULL) { + new->trash_stack[UCL_TRASH_KEY] = + strdup (other->trash_stack[UCL_TRASH_KEY]); + if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) { + new->key = new->trash_stack[UCL_TRASH_KEY]; + } + } + if (other->trash_stack[UCL_TRASH_VALUE] != NULL) { + new->trash_stack[UCL_TRASH_VALUE] = + strdup (other->trash_stack[UCL_TRASH_VALUE]); + if (new->type == UCL_STRING) { + new->value.sv = new->trash_stack[UCL_TRASH_VALUE]; + } + } + + if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) { + /* reset old value */ + memset (&new->value, 0, sizeof (new->value)); + + while ((cur = ucl_iterate_object (other, &it, true)) != NULL) { + if (other->type == UCL_ARRAY) { + ucl_array_append (new, ucl_object_copy_internal (cur, false)); + } + else { + ucl_object_t *cp = ucl_object_copy_internal (cur, true); + if (cp != NULL) { + ucl_object_insert_key (new, cp, cp->key, cp->keylen, + false); + } + } + } + } + else if (allow_array && other->next != NULL) { + LL_FOREACH (other->next, cur) { + ucl_object_t *cp = ucl_object_copy_internal (cur, false); + if (cp != NULL) { + DL_APPEND (new, cp); + } + } + } + } + + return new; +} + +ucl_object_t * +ucl_object_copy (const ucl_object_t *other) +{ + return ucl_object_copy_internal (other, true); +} + void ucl_object_unref (ucl_object_t *obj) { @@ -1956,3 +2383,25 @@ ucl_object_array_sort (ucl_object_t *ar, DL_SORT (ar->value.av, cmp); } + +#define PRIOBITS 4 + +unsigned int +ucl_object_get_priority (const ucl_object_t *obj) +{ + if (obj == NULL) { + return 0; + } + + return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS)); +} + +void +ucl_object_set_priority (ucl_object_t *obj, + unsigned int priority) +{ + if (obj != NULL) { + priority &= (0x1 << PRIOBITS) - 1; + obj->flags |= priority << ((sizeof (obj->flags) * NBBY) - PRIOBITS); + } +} diff --git a/contrib/libucl/tests/Makefile.am b/contrib/libucl/tests/Makefile.am index a21a65c16534..5b17e1fb252e 100644 --- a/contrib/libucl/tests/Makefile.am +++ b/contrib/libucl/tests/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = $(TESTS) basic schema generate.res rcl_test.json.xz +EXTRA_DIST = $(TESTS) basic schema generate.res streamline.res rcl_test.json.xz TESTS = basic.test \ generate.test \ diff --git a/contrib/libucl/tests/basic/12.in b/contrib/libucl/tests/basic/12.in new file mode 100644 index 000000000000..b63a32fbf92d --- /dev/null +++ b/contrib/libucl/tests/basic/12.in @@ -0,0 +1,2 @@ +key1: 12 , +key2: 12 value diff --git a/contrib/libucl/tests/basic/12.res b/contrib/libucl/tests/basic/12.res new file mode 100644 index 000000000000..163af46c7f17 --- /dev/null +++ b/contrib/libucl/tests/basic/12.res @@ -0,0 +1,3 @@ +key1 = 12; +key2 = "12 value"; + diff --git a/contrib/libucl/tests/basic/13.in b/contrib/libucl/tests/basic/13.in new file mode 100644 index 000000000000..81f03a61d286 --- /dev/null +++ b/contrib/libucl/tests/basic/13.in @@ -0,0 +1,9 @@ +key = value_orig; + +# test glob +.include(glob=true) "${CURDIR}/include_dir/test*.conf" + +.include(priority=1) "${CURDIR}/include_dir/pri1.conf" +.include(priority=2) "${CURDIR}/include_dir/pri2.conf" + +.include(try=true) "${CURDIR}/include_dir/invalid.conf" diff --git a/contrib/libucl/tests/basic/13.res b/contrib/libucl/tests/basic/13.res new file mode 100644 index 000000000000..aa13a5471f2e --- /dev/null +++ b/contrib/libucl/tests/basic/13.res @@ -0,0 +1,8 @@ +key = "value_orig"; +key = "value1"; +key = "value2"; +key = "value3"; +key_pri = "priority2"; +key_trace1 = "pri1"; +key_trace2 = "pri2"; + diff --git a/contrib/libucl/tests/basic/4.res b/contrib/libucl/tests/basic/4.res index 58c3599432b8..2b862fc1410a 100644 --- a/contrib/libucl/tests/basic/4.res +++ b/contrib/libucl/tests/basic/4.res @@ -10,7 +10,14 @@ licenses [ "BSD", ] flatsize = 60523; -desc = "pkgconf is a program which helps to configure compiler and linker flags for\ndevelopment frameworks. It is similar to pkg-config, but was written from\nscratch in Summer of 2011 to replace pkg-config, which now needs itself to build\nitself.\n\nWWW: https://github.com/pkgconf/pkgconf"; +desc = <type == UCL_OBJECT) { printf ("%stype: UCL_OBJECT\n", pre); printf ("%svalue: %p\n", pre, obj->value.ov); + it_obj = NULL; while ((cur = ucl_iterate_object (obj, &it_obj, true))) { ucl_obj_dump (cur, shift + 2); } diff --git a/contrib/mdocml/lib.in b/contrib/mdocml/lib.in index a785c72e123e..d48db35152f3 100644 --- a/contrib/mdocml/lib.in +++ b/contrib/mdocml/lib.in @@ -56,6 +56,7 @@ LINE("libftpio", "FTP Connection Management Library (libftpio, \\-lftpio)") LINE("libform", "Curses Form Library (libform, \\-lform)") LINE("libgeom", "Userland API Library for Kernel GEOM subsystem (libgeom, \\-lgeom)") LINE("libgpib", "General-Purpose Instrument Bus (GPIB) library (libgpib, \\-lgpib)") +LINE("libgpio", "General-Purpose Input Output (GPIO) library (libgpio, \\-lgpio)") LINE("libhammer", "HAMMER Filesystem Userland Library (libhammer, \\-lhammer)") LINE("libi386", "i386 Architecture Library (libi386, \\-li386)") LINE("libintl", "Internationalized Message Handling Library (libintl, \\-lintl)") diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c b/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c index ed43df57eb04..46c0ff1a71f7 100644 --- a/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c +++ b/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c @@ -51,7 +51,11 @@ run(int n, ...) ATF_REQUIRE_EQ(n, DEPTH - calls - 1); va_start(va, n); +#if defined(__FreeBSD__) && defined(__amd64__) + for (i = 0; i < 5; i++) { +#else for (i = 0; i < 9; i++) { +#endif ia = va_arg(va, int); ATF_REQUIRE_EQ(i, ia); } @@ -101,13 +105,6 @@ ATF_TC_BODY(setcontext_link, tc) ucontext_t save; volatile int i = 0; /* avoid longjmp clobbering */ -#ifdef __FreeBSD__ -#ifdef __amd64__ - atf_tc_expect_fail("setcontext in this testcase fails on " - "FreeBSD/amd64 with rc == -1/errno == EINVAL; see PR # 194828"); -#endif -#endif - for (i = 0; i < DEPTH; ++i) { ATF_REQUIRE_EQ(getcontext(&uc[i]), 0); @@ -115,21 +112,20 @@ ATF_TC_BODY(setcontext_link, tc) uc[i].uc_stack.ss_size = STACKSZ; uc[i].uc_link = (i > 0) ? &uc[i - 1] : &save; +#if defined(__FreeBSD__) && defined(__amd64__) + /* FreeBSD/amd64 only permits up to 6 arguments. */ + makecontext(&uc[i], (void *)run, 6, i, + 0, 1, 2, 3, 4); +#else makecontext(&uc[i], (void *)run, 10, i, 0, 1, 2, 3, 4, 5, 6, 7, 8); +#endif } ATF_REQUIRE_EQ(getcontext(&save), 0); -#ifdef __FreeBSD__ - if (calls == 0) { - int rc = setcontext(&uc[DEPTH-1]); - ATF_REQUIRE_EQ_MSG(rc, 0, "%d != 0; (errno = %d)", rc, errno); - } -#else if (calls == 0) ATF_REQUIRE_EQ(setcontext(&uc[DEPTH-1]), 0); -#endif } ATF_TP_ADD_TCS(tp) diff --git a/contrib/ofed/libmlx4/src/cq.c b/contrib/ofed/libmlx4/src/cq.c index eef1e0258253..ef01fcfdb151 100644 --- a/contrib/ofed/libmlx4/src/cq.c +++ b/contrib/ofed/libmlx4/src/cq.c @@ -109,15 +109,16 @@ struct mlx4_err_cqe { static struct mlx4_cqe *get_cqe(struct mlx4_cq *cq, int entry) { - return cq->buf.buf + entry * MLX4_CQ_ENTRY_SIZE; + return cq->buf.buf + entry * cq->cqe_size; } static void *get_sw_cqe(struct mlx4_cq *cq, int n) { struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibv_cq.cqe); + struct mlx4_cqe *tcqe = cq->cqe_size == 64 ? cqe + 1 : cqe; - return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^ - !!(n & (cq->ibv_cq.cqe + 1))) ? NULL : cqe; + return (!!(tcqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^ + !!(n & (cq->ibv_cq.cqe + 1))) ? NULL : tcqe; } static struct mlx4_cqe *next_cqe_sw(struct mlx4_cq *cq) @@ -402,6 +403,7 @@ void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) uint8_t owner_bit; int nfreed = 0; int is_xrc_srq = 0; + int cqe_inc = cq->cqe_size == 64 ? 1 : 0; if (srq && srq->ibv_srq.xrc_cq) is_xrc_srq = 1; @@ -423,6 +425,7 @@ void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) */ while ((int) --prod_index - (int) cq->cons_index >= 0) { cqe = get_cqe(cq, prod_index & cq->ibv_cq.cqe); + cqe += cqe_inc; if (is_xrc_srq && (ntohl(cqe->g_mlpath_rqpn & 0xffffff) == srq->srqn) && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK)) { @@ -434,6 +437,7 @@ void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) ++nfreed; } else if (nfreed) { dest = get_cqe(cq, (prod_index + nfreed) & cq->ibv_cq.cqe); + dest += cqe_inc; owner_bit = dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK; memcpy(dest, cqe, sizeof *cqe); dest->owner_sr_opcode = owner_bit | @@ -473,28 +477,32 @@ void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int old_cqe) { struct mlx4_cqe *cqe; int i; + int cqe_inc = cq->cqe_size == 64 ? 1 : 0; i = cq->cons_index; cqe = get_cqe(cq, (i & old_cqe)); + cqe += cqe_inc; while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) { cqe->owner_sr_opcode = (cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK) | (((i + 1) & (cq->ibv_cq.cqe + 1)) ? MLX4_CQE_OWNER_MASK : 0); - memcpy(buf + ((i + 1) & cq->ibv_cq.cqe) * MLX4_CQ_ENTRY_SIZE, - cqe, MLX4_CQ_ENTRY_SIZE); + memcpy(buf + ((i + 1) & cq->ibv_cq.cqe) * cq->cqe_size, + cqe - cqe_inc, cq->cqe_size); ++i; cqe = get_cqe(cq, (i & old_cqe)); + cqe += cqe_inc; } ++cq->cons_index; } -int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent) +int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent, + int entry_size) { - if (mlx4_alloc_buf(buf, align(nent * MLX4_CQ_ENTRY_SIZE, dev->page_size), + if (mlx4_alloc_buf(buf, align(nent * entry_size, dev->page_size), dev->page_size)) return -1; - memset(buf->buf, 0, nent * MLX4_CQ_ENTRY_SIZE); + memset(buf->buf, 0, nent * entry_size); return 0; } diff --git a/contrib/ofed/libmlx4/src/mlx4-abi.h b/contrib/ofed/libmlx4/src/mlx4-abi.h index cc054e419579..86be5c7fb137 100644 --- a/contrib/ofed/libmlx4/src/mlx4-abi.h +++ b/contrib/ofed/libmlx4/src/mlx4-abi.h @@ -40,9 +40,11 @@ struct mlx4_alloc_ucontext_resp { struct ibv_get_context_resp ibv_resp; + __u32 dev_caps; __u32 qp_tab_size; __u16 bf_reg_size; __u16 bf_regs_per_page; + __u32 cqe_size; }; struct mlx4_alloc_pd_resp { diff --git a/contrib/ofed/libmlx4/src/mlx4.c b/contrib/ofed/libmlx4/src/mlx4.c index 17adb300a9a8..caabced39a7e 100644 --- a/contrib/ofed/libmlx4/src/mlx4.c +++ b/contrib/ofed/libmlx4/src/mlx4.c @@ -201,6 +201,7 @@ static struct ibv_context *mlx4_alloc_context(struct ibv_device *ibdev, int cmd_ context->bf_buf_size = 0; } + context->cqe_size = resp.cqe_size; pthread_spin_init(&context->uar_lock, PTHREAD_PROCESS_PRIVATE); context->ibv_ctx.ops = mlx4_ctx_ops; diff --git a/contrib/ofed/libmlx4/src/mlx4.h b/contrib/ofed/libmlx4/src/mlx4.h index a349c5b805b4..cf5b963c16bc 100644 --- a/contrib/ofed/libmlx4/src/mlx4.h +++ b/contrib/ofed/libmlx4/src/mlx4.h @@ -102,10 +102,6 @@ _a < _b ? _a : _b; }) #endif -enum { - MLX4_CQ_ENTRY_SIZE = 0x20 -}; - enum { MLX4_STAT_RATE_OFFSET = 5 }; @@ -192,6 +188,7 @@ struct mlx4_context { int max_qp_wr; int max_sge; int max_cqe; + int cqe_size; struct { struct mlx4_srq **table; @@ -226,6 +223,7 @@ struct mlx4_cq { uint32_t *set_ci_db; uint32_t *arm_db; int arm_sn; + int cqe_size; }; struct mlx4_srq { @@ -369,7 +367,8 @@ int mlx4_dereg_mr(struct ibv_mr *mr); struct ibv_cq *mlx4_create_cq(struct ibv_context *context, int cqe, struct ibv_comp_channel *channel, int comp_vector); -int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent); +int mlx4_alloc_cq_buf(struct mlx4_device *dev, struct mlx4_buf *buf, int nent, + int entry_size); int mlx4_resize_cq(struct ibv_cq *cq, int cqe); int mlx4_destroy_cq(struct ibv_cq *cq); int mlx4_poll_cq(struct ibv_cq *cq, int ne, struct ibv_wc *wc); diff --git a/contrib/ofed/libmlx4/src/verbs.c b/contrib/ofed/libmlx4/src/verbs.c index 45e86935a37f..1a806984ef09 100644 --- a/contrib/ofed/libmlx4/src/verbs.c +++ b/contrib/ofed/libmlx4/src/verbs.c @@ -168,6 +168,7 @@ struct ibv_cq *mlx4_create_cq(struct ibv_context *context, int cqe, struct mlx4_create_cq_resp resp; struct mlx4_cq *cq; int ret; + struct mlx4_context *mctx = to_mctx(context); /* Sanity check CQ size before proceeding */ if (cqe > 0x3fffff) @@ -184,9 +185,11 @@ struct ibv_cq *mlx4_create_cq(struct ibv_context *context, int cqe, cqe = align_queue_size(cqe + 1); - if (mlx4_alloc_cq_buf(to_mdev(context->device), &cq->buf, cqe)) + if (mlx4_alloc_cq_buf(to_mdev(context->device), &cq->buf, cqe, mctx->cqe_size)) goto err; + cq->cqe_size = mctx->cqe_size; + cq->set_ci_db = mlx4_alloc_db(to_mctx(context), MLX4_DB_TYPE_CQ); if (!cq->set_ci_db) goto err_buf; @@ -247,7 +250,8 @@ int mlx4_resize_cq(struct ibv_cq *ibcq, int cqe) goto out; } - ret = mlx4_alloc_cq_buf(to_mdev(ibcq->context->device), &buf, cqe); + ret = mlx4_alloc_cq_buf(to_mdev(ibcq->context->device), &buf, cqe, + cq->cqe_size); if (ret) goto out; diff --git a/gnu/lib/libdialog/Makefile b/gnu/lib/libdialog/Makefile index 3945cc01e22f..1df11ec3640e 100644 --- a/gnu/lib/libdialog/Makefile +++ b/gnu/lib/libdialog/Makefile @@ -13,8 +13,7 @@ SRCS= argv.c arrows.c buildlist.c buttons.c calendar.c checklist.c \ INCS= dialog.h dlg_colors.h dlg_config.h dlg_keys.h MAN= dialog.3 -DPADD= ${LIBNCURSESW} ${LIBM} -LDADD= -lncursesw -lm +LIBADD= ncursesw m CFLAGS+= -I${.CURDIR} -I${DIALOG} -D_XOPEN_SOURCE_EXTENDED -DGCC_UNUSED=__unused .PATH: ${DIALOG} diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile index 4fd8b8d45147..e7d10b23f1b4 100644 --- a/gnu/lib/libgcc/Makefile +++ b/gnu/lib/libgcc/Makefile @@ -28,8 +28,7 @@ CFLAGS+= -DIN_GCC -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \ -I${.CURDIR}/../../usr.bin/cc/cc_tools LDFLAGS+= -nodefaultlibs -DPADD+= ${LIBC} -LDADD+= -lc +LIBADD+= c OBJS= # added to below in various ways depending on TARGET_CPUARCH @@ -119,8 +118,7 @@ LIB1ASMSRC = lib1funcs.asm LIB1ASMFUNCS = _dvmd_tls _bb_init_func LIB2ADDEH = unwind-arm.c libunwind.S pr-support.c unwind-c.c # Some compilers generate __aeabi_ functions libgcc_s is missing -DPADD+= ${LIBCOMPILER_RT} -LDADD+= -lcompiler_rt +LIBADD+= compiler_rt .endif .if ${TARGET_CPUARCH} == mips diff --git a/gnu/lib/libreadline/readline/Makefile b/gnu/lib/libreadline/readline/Makefile index f09e9432a5fa..2afeafc61f82 100644 --- a/gnu/lib/libreadline/readline/Makefile +++ b/gnu/lib/libreadline/readline/Makefile @@ -23,7 +23,6 @@ ${.OBJDIR}/${_h}: ${SRCDIR}/${_h} ${INSTALL} ${.ALLSRC} ${.TARGET} .endfor -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw .include diff --git a/gnu/lib/libstdc++/Makefile b/gnu/lib/libstdc++/Makefile index 98a08f416499..d55b67ef4734 100644 --- a/gnu/lib/libstdc++/Makefile +++ b/gnu/lib/libstdc++/Makefile @@ -23,8 +23,8 @@ CXXFLAGS+= -fno-implicit-templates -ffunction-sections -fdata-sections \ -Wno-deprecated PO_CXXFLAGS= ${CXXFLAGS:N-ffunction-sections} -DPADD= ${LIBM} -LDADD= -lm -Wl,-f,libsupc++.so.1 +LIBADD+= m +LDADD= -Wl,-f,libsupc++.so.1 # libstdc++ sources SRCS+= bitmap_allocator.cc pool_allocator.cc \ diff --git a/gnu/usr.bin/binutils/Makefile b/gnu/usr.bin/binutils/Makefile index 1ba36a6a2660..a544bc54b32d 100644 --- a/gnu/usr.bin/binutils/Makefile +++ b/gnu/usr.bin/binutils/Makefile @@ -1,7 +1,19 @@ # $FreeBSD$ -SUBDIR= libiberty libbfd libopcodes libbinutils \ - addr2line as ld nm objcopy objdump readelf \ - size strings strip doc +SUBDIR= libiberty \ + libbfd \ + libopcodes \ + libbinutils \ + addr2line \ + as \ + ld \ + nm \ + objcopy \ + objdump \ + readelf \ + size \ + strings \ + strip \ + doc .include diff --git a/gnu/usr.bin/dialog/Makefile b/gnu/usr.bin/dialog/Makefile index f9281c8fd685..ae1f1ab0af8f 100644 --- a/gnu/usr.bin/dialog/Makefile +++ b/gnu/usr.bin/dialog/Makefile @@ -3,8 +3,7 @@ DIALOG= ${.CURDIR}/../../../contrib/dialog PROG= dialog -DPADD= ${LIBDIALOG} ${LIBNCURSESW} ${LIBM} -LDADD= -ldialog -lncursesw -lm +LIBADD= dialog ncursesw m CFLAGS+= -I${.CURDIR} -I${DIALOG} .PATH: ${DIALOG} diff --git a/gnu/usr.bin/diff/Makefile b/gnu/usr.bin/diff/Makefile index 6b29df5c0e98..03d2fec21639 100644 --- a/gnu/usr.bin/diff/Makefile +++ b/gnu/usr.bin/diff/Makefile @@ -26,8 +26,7 @@ CFLAGS+=-I${DESTDIR}/usr/include/gnu SUBDIR+=doc -DPADD= ${LIBGNUREGEX} -LDADD= -lgnuregex +LIBADD+= gnuregex .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/gnu/usr.bin/gdb/gdb/Makefile b/gnu/usr.bin/gdb/gdb/Makefile index 900fbcce084d..7e64ed106df8 100644 --- a/gnu/usr.bin/gdb/gdb/Makefile +++ b/gnu/usr.bin/gdb/gdb/Makefile @@ -11,8 +11,9 @@ GDBLIBS= ${OBJ_GDB}/libgdb/libgdb.a # global symbols visible. LDFLAGS+= -Wl,-E -DPADD= ${GDBLIBS} ${BULIBS} ${LIBM} ${LIBREADLINE} ${LIBTERMCAPW} ${LIBGNUREGEX} -LDADD= ${GDBLIBS} ${BULIBS} -lm ${LDREADLINE} -ltermcapw -lgnuregex +DPADD= ${GDBLIBS} ${BULIBS} +LDADD= ${GDBLIBS} ${BULIBS} +LIBADD+= m readline ncursesw gnuregex .include CFLAGS+= -DDEBUGDIR=\"${DEBUGDIR}\" diff --git a/gnu/usr.bin/gdb/gdbtui/Makefile b/gnu/usr.bin/gdb/gdbtui/Makefile index 4ee9415da22a..7912d04ec9fa 100644 --- a/gnu/usr.bin/gdb/gdbtui/Makefile +++ b/gnu/usr.bin/gdb/gdbtui/Makefile @@ -12,7 +12,8 @@ GDBLIBS= ${OBJ_GDB}/libgdb/libgdb.a # global symbols visible. LDFLAGS+= -Wl,-E -DPADD= ${GDBLIBS} ${BULIBS} ${LIBM} ${LIBREADLINE} ${LIBTERMCAPW} ${LIBGNUREGEX} -LDADD= ${GDBLIBS} ${BULIBS} -lm ${LDREADLINE} -ltermcapw -lgnuregex +DPADD= ${GDBLIBS} ${BULIBS} +LDADD= ${GDBLIBS} ${BULIBS} +LIBADD+= m readline ncursesw gnuregex .include diff --git a/gnu/usr.bin/gdb/kgdb/Makefile b/gnu/usr.bin/gdb/kgdb/Makefile index 04c14b30fbc2..8af2e1821edb 100644 --- a/gnu/usr.bin/gdb/kgdb/Makefile +++ b/gnu/usr.bin/gdb/kgdb/Makefile @@ -8,10 +8,9 @@ BULIBS= ${OBJ_BU}/libbfd/libbfd.a ${OBJ_BU}/libopcodes/libopcodes.a \ ${OBJ_BU}/libiberty/libiberty.a GDBLIBS= ${OBJ_GDB}/libgdb/libgdb.a -DPADD= ${GDBLIBS} ${BULIBS} ${LIBKVM} ${LIBM} ${LIBREADLINE} ${LIBTERMCAPW} \ - ${LIBGNUREGEX} -LDADD= ${GDBLIBS} ${BULIBS} -lkvm${GDB_SUFFIX} -lm ${LDREADLINE} -ltermcapw \ - -lgnuregex +DPADD= ${GDBLIBS} ${BULIBS} ${LIBKVM} +LDADD= ${GDBLIBS} ${BULIBS} -lkvm${GDB_SUFFIX} +LIBADD+= m readline ncursesw gnuregex .if defined(GDB_CROSS_DEBUGGER) CFLAGS+= -Wl,-export-dynamic diff --git a/gnu/usr.bin/grep/Makefile b/gnu/usr.bin/grep/Makefile index 5221f2fdc352..3669d1fc8bfc 100644 --- a/gnu/usr.bin/grep/Makefile +++ b/gnu/usr.bin/grep/Makefile @@ -22,8 +22,7 @@ LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \ MLINKS= grep.1 egrep.1 grep.1 fgrep.1 .endif -DPADD= ${LIBGNUREGEX} ${LIBBZ2} -LDADD= -lgnuregex -lbz2 +LIBADD= gnuregex bz2 .if ${MK_BSD_GREP} != "yes" LINKS+= ${BINDIR}/grep ${BINDIR}/bzgrep \ @@ -33,8 +32,7 @@ MLINKS+=grep.1 bzgrep.1 grep.1 bzegrep.1 grep.1 bzfgrep.1 .endif .if defined(GREP_LIBZ) && !empty(GREP_LIBZ) -LDADD+= -lz -DPADD+= ${LIBZ} +LIBADD+= z CFLAGS+=-DHAVE_LIBZ=1 .if ${MK_BSD_GREP} != "yes" LINKS+= ${BINDIR}/grep ${BINDIR}/zgrep \ diff --git a/kerberos5/Makefile.inc b/kerberos5/Makefile.inc index f53eadd6f47f..6048589df445 100644 --- a/kerberos5/Makefile.inc +++ b/kerberos5/Makefile.inc @@ -16,9 +16,6 @@ LDAPCFLAGS= -I${OPENLDAPBASE}/include -DOPENLDAP=1 -DLDAP_DEPRECATED=1 LDAPLDFLAGS= -L${OPENLDAPBASE}/lib -Wl,-rpath,${OPENLDAPBASE}/lib .endif -LIBVERS= ${.OBJDIR}/../../lib/libvers/libvers.a -LIBSL= ${.OBJDIR}/../../lib/libsl/libsl.a - .if defined(SRCS) ETSRCS= \ diff --git a/kerberos5/lib/libasn1/Makefile b/kerberos5/lib/libasn1/Makefile index 02e6a4975fd4..d445b8b386d4 100644 --- a/kerberos5/lib/libasn1/Makefile +++ b/kerberos5/lib/libasn1/Makefile @@ -3,8 +3,7 @@ LIB= asn1 LDFLAGS= -Wl,--no-undefined INCS= asn1_err.h asn1-common.h heim_asn1.h der.h der-protos.h der-private.h -LDADD= -lcom_err -lroken -DPADD= ${LIBCOM_ERR} ${LIBROKEN} +LIBADD= com_err roken VERSION_MAP= ${.CURDIR}/version.map SRCS= asn1_err.c \ diff --git a/kerberos5/lib/libgssapi_krb5/Makefile b/kerberos5/lib/libgssapi_krb5/Makefile index a883c7d4d8ae..6116767e45a4 100644 --- a/kerberos5/lib/libgssapi_krb5/Makefile +++ b/kerberos5/lib/libgssapi_krb5/Makefile @@ -2,9 +2,7 @@ LIB= gssapi_krb5 LDFLAGS= -Wl,-Bsymbolic -Wl,--no-undefined -LDADD= -lgssapi -lkrb5 -lhx509 -lcrypto -lroken -lasn1 -lcom_err -lcrypt -DPADD= ${LIBGSSAPI} ${LIBKRB5} ${LIBHX509} ${LIBCRYPTO} ${LIBROKEN} ${LIBASN1} \ - ${LIBCOM_ERR} ${LIBCRYPT} +LIBADD= gssapi krb5 crypto roken asn1 com_err SHLIB_MAJOR= 10 INCS= ${KRB5DIR}/lib/gssapi/gssapi/gssapi_krb5.h diff --git a/kerberos5/lib/libgssapi_ntlm/Makefile b/kerberos5/lib/libgssapi_ntlm/Makefile index cfe071677a32..ac546f716642 100644 --- a/kerberos5/lib/libgssapi_ntlm/Makefile +++ b/kerberos5/lib/libgssapi_ntlm/Makefile @@ -2,8 +2,7 @@ LIB= gssapi_ntlm LDFLAGS= -Wl,-Bsymbolic -Wl,--no-undefined -LDADD= -lcrypto -lgssapi -lkrb5 -lhx509 -lheimntlm -lroken -DPADD= ${LIBCRYPTO} ${LIBGSSAPI} ${LIBKRB5} ${LIBHX509} ${LIBHEIMNTLM} ${LIBROKEN} +LIBADD= crypto gssapi krb5 heimntlm roken SHLIB_MAJOR= 10 SRCS= accept_sec_context.c \ diff --git a/kerberos5/lib/libgssapi_spnego/Makefile b/kerberos5/lib/libgssapi_spnego/Makefile index 09062655d0e1..92168082b417 100644 --- a/kerberos5/lib/libgssapi_spnego/Makefile +++ b/kerberos5/lib/libgssapi_spnego/Makefile @@ -2,8 +2,7 @@ LIB= gssapi_spnego LDFLAGS= -Wl,-Bsymbolic -Wl,--no-undefined -LDADD= -lgssapi -lheimbase -lasn1 -lroken -DPADD= ${LIBGSSAPI} ${LIBHEIMBASE} ${LIBASN1} ${LIBROKEN} +LIBADD= gssapi heimbase asn1 roken SHLIB_MAJOR= 10 SRCS= accept_sec_context.c \ diff --git a/kerberos5/lib/libhdb/Makefile b/kerberos5/lib/libhdb/Makefile index a1ed80612896..1f99fc451731 100644 --- a/kerberos5/lib/libhdb/Makefile +++ b/kerberos5/lib/libhdb/Makefile @@ -3,8 +3,8 @@ LIB= hdb LDFLAGS= -Wl,--no-undefined VERSION_MAP= ${KRB5DIR}/lib/hdb/version-script.map -LDADD= -lasn1 -lcom_err -lkrb5 -lroken -lheimsqlite -DPADD= ${LIBASN1} ${LIBCOM_ERR} ${LIBKRB5} ${LIBROKEN} ${LIBHEIMSQLITE} ${LDAPDPADD} +LIBADD= asn1 com_err krb5 roken heimsqlite +DPADD= ${LDAPDPADD} MAN= HDB.3 hdb_entry_ex.3 diff --git a/kerberos5/lib/libheimbase/Makefile b/kerberos5/lib/libheimbase/Makefile index b6a61d0e9e0d..b6bf526b3522 100644 --- a/kerberos5/lib/libheimbase/Makefile +++ b/kerberos5/lib/libheimbase/Makefile @@ -2,7 +2,7 @@ LIB= heimbase LDFLAGS= -Wl,--no-undefined -LDADD= -lpthread +LIBADD= pthread VERSION_MAP= ${KRB5DIR}/base/version-script.map INCS= heimbase.h diff --git a/kerberos5/lib/libheimipcc/Makefile b/kerberos5/lib/libheimipcc/Makefile index eaab2d24d1fb..1016541af412 100644 --- a/kerberos5/lib/libheimipcc/Makefile +++ b/kerberos5/lib/libheimipcc/Makefile @@ -2,8 +2,7 @@ LIB= heimipcc PRIVATELIB= -LDADD= -lheimbase -lroken -lpthread -DPADD= ${LIBHEIMBASE} ${LIBROKEN} ${LIBPTHREAD} +LIBADD= heimbase roken pthread SRCS= \ client.c \ diff --git a/kerberos5/lib/libheimipcs/Makefile b/kerberos5/lib/libheimipcs/Makefile index 31fd4afa1a56..b1201f65a842 100644 --- a/kerberos5/lib/libheimipcs/Makefile +++ b/kerberos5/lib/libheimipcs/Makefile @@ -2,9 +2,7 @@ LIB= heimipcs PRIVATELIB= -LDADD= -lheimbase -lroken -LDFLAGS= -pthread -DPADD= ${LIBHEIMBASE} ${LIBROKEN} +LIBADD= heimbase roken pthread SRCS= \ server.c \ diff --git a/kerberos5/lib/libheimntlm/Makefile b/kerberos5/lib/libheimntlm/Makefile index 2f0415d9b42e..d35fc38accae 100644 --- a/kerberos5/lib/libheimntlm/Makefile +++ b/kerberos5/lib/libheimntlm/Makefile @@ -2,8 +2,7 @@ LIB= heimntlm LDFLAGS= -Wl,--no-undefined -LDADD= -lcrypto -lcom_err -lkrb5 -lroken -DPADD= ${LIBCRYPTO} ${LIBCOM_ERR} ${LIBKRB5} ${LIBROKEN} +LIBADD= crypto com_err krb5 roken SRCS= ntlm.c ntlm_err.c INCS= heimntlm.h heimntlm-protos.h ntlm_err.h CFLAGS+=-I${KRB5DIR}/lib/ntlm -I${KRB5DIR}/lib/roken diff --git a/kerberos5/lib/libheimsqlite/Makefile b/kerberos5/lib/libheimsqlite/Makefile index b98537a3324f..8cad7e7202ad 100644 --- a/kerberos5/lib/libheimsqlite/Makefile +++ b/kerberos5/lib/libheimsqlite/Makefile @@ -2,8 +2,7 @@ LIB= heimsqlite SRCS= sqlite3.c -DPADD= ${LIBPTHREAD} -LDADD= -lpthread +LIBADD= pthread CFLAGS+=-I${KRB5DIR}/lib/sqlite .include diff --git a/kerberos5/lib/libhx509/Makefile b/kerberos5/lib/libhx509/Makefile index 3bffda6eb0e4..66e456d88cc9 100644 --- a/kerberos5/lib/libhx509/Makefile +++ b/kerberos5/lib/libhx509/Makefile @@ -3,8 +3,7 @@ LIB= hx509 LDFLAGS= -Wl,--no-undefined VERSION_MAP= ${KRB5DIR}/lib/hx509/version-script.map -LDADD= -lasn1 -lcom_err -lcrypto -lroken -lwind -DPADD= ${LIBASN1} ${LIBCOM_ERR} ${LIBCRYPTO} ${LIBROKEN} ${LIBWIND} +LIBADD= asn1 com_err crypto roken wind MAN= hx509.3 \ hx509_ca.3 \ diff --git a/kerberos5/lib/libkadm5clnt/Makefile b/kerberos5/lib/libkadm5clnt/Makefile index c413b5d3cac8..1f3401e636d5 100644 --- a/kerberos5/lib/libkadm5clnt/Makefile +++ b/kerberos5/lib/libkadm5clnt/Makefile @@ -2,8 +2,7 @@ LIB= kadm5clnt LDFLAGS= -Wl,--no-undefined -LDADD= -lcom_err -lkrb5 -lroken -DPADD= ${LIBCOM_ERR} ${LIBKRB5} ${LIBROKEN} +LIBADD= com_err krb5 roken INCS= admin.h \ kadm5-private.h \ diff --git a/kerberos5/lib/libkadm5srv/Makefile b/kerberos5/lib/libkadm5srv/Makefile index 5c3a1916880c..adf49a5b1af5 100644 --- a/kerberos5/lib/libkadm5srv/Makefile +++ b/kerberos5/lib/libkadm5srv/Makefile @@ -2,8 +2,7 @@ LIB= kadm5srv LDFLAGS= -Wl,--no-undefined -LDADD= -lcom_err -lhdb -lkrb5 -lroken -DPADD= ${LIBCOM_ERR} ${LIBHDB} ${LIBKRB5} ${LIBROKEN} +LIBADD= com_err hdb krb5 roken VERSION_MAP= ${KRB5DIR}/lib/kadm5/version-script.map MAN= kadm5_pwcheck.3 diff --git a/kerberos5/lib/libkafs5/Makefile b/kerberos5/lib/libkafs5/Makefile index 6d66578cb247..6b7a4cda6d7a 100644 --- a/kerberos5/lib/libkafs5/Makefile +++ b/kerberos5/lib/libkafs5/Makefile @@ -1,9 +1,8 @@ # $FreeBSD$ LIB= kafs5 -LDADD= -lasn1 -lroken -lkrb5 LDFLAGS= -Wl,--no-undefined -DPADD= ${LIBASN1} ${LIBKRB5} ${LIBROKEN} +LIBADD= asn1 krb5 roken INCS= kafs.h MAN= kafs5.3 VERSION_MAP= ${.CURDIR}/version.map diff --git a/kerberos5/lib/libkdc/Makefile b/kerberos5/lib/libkdc/Makefile index fa9792da08b6..14b0797e2738 100644 --- a/kerberos5/lib/libkdc/Makefile +++ b/kerberos5/lib/libkdc/Makefile @@ -3,9 +3,7 @@ LIB= kdc LDFLAGS= -Wl,--no-undefined VERSION_MAP= ${KRB5DIR}/kdc/version-script.map -LDADD= -lroken -lhdb -lhx509 -lkrb5 -lheimntlm -lasn1 -lcrypt -lcrypto -DPADD= ${LIBROKEN} ${LIBHDB} ${LIBHX509} ${LIBKRB5} ${LIBHEIMNTLM} \ - ${LIBASN1} ${LIBCRYPT} ${LIBCRYPTO} +LIBADD= roken hdb hx509 krb5 heimntlm asn1 crypto INCS= kdc.h \ kdc-protos.h diff --git a/kerberos5/lib/libkrb5/Makefile b/kerberos5/lib/libkrb5/Makefile index 4128762967a5..a1999ccf3e63 100644 --- a/kerberos5/lib/libkrb5/Makefile +++ b/kerberos5/lib/libkrb5/Makefile @@ -3,9 +3,7 @@ LIB= krb5 LDFLAGS= -Wl,--no-undefined VERSION_MAP= ${KRB5DIR}/lib/krb5/version-script.map -LDADD= -lasn1 -lcom_err -lcrypt -lcrypto -lhx509 -lroken -lwind -lheimbase ${LDHEIMIPCC} -DPADD= ${LIBASN1} ${LIBCOM_ERR} ${LIBCRYPT} ${LIBCRYPTO} ${LIBHX509} ${LIBROKEN} ${LIBWIND} ${LIBHEIMBASE} ${LIBHEIMIPCC} -USEPRIVATELIB= heimipcc +LIBADD= asn1 com_err crypt crypto hx509 roken wind heimbase heimipcc INCS= heim_err.h \ heim_threads.h \ diff --git a/kerberos5/lib/libroken/Makefile b/kerberos5/lib/libroken/Makefile index cf9368bbf3ee..aade99ae625b 100644 --- a/kerberos5/lib/libroken/Makefile +++ b/kerberos5/lib/libroken/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ LIB= roken -LDADD= -lcrypt -DPADD= ${LIBCRYPT} +LIBADD= crypt VERSION_MAP= ${KRB5DIR}/lib/roken/version-script.map INCS= roken.h \ roken-common.h \ diff --git a/kerberos5/lib/libwind/Makefile b/kerberos5/lib/libwind/Makefile index 6d0b9c08e200..a489566efbb3 100644 --- a/kerberos5/lib/libwind/Makefile +++ b/kerberos5/lib/libwind/Makefile @@ -3,8 +3,7 @@ LIB= wind LDFLAGS= -Wl,--no-undefined VERSION_MAP= ${KRB5DIR}/lib/wind/version-script.map -LDADD= -lcom_err -lroken -DPADD= ${LIBCOM_ERR} ${LIBROKEN} +LIBADD= com_err roken INCS= wind.h \ wind_err.h diff --git a/kerberos5/libexec/digest-service/Makefile b/kerberos5/libexec/digest-service/Makefile index 0c45c37ed1cb..f018aac64da8 100644 --- a/kerberos5/libexec/digest-service/Makefile +++ b/kerberos5/libexec/digest-service/Makefile @@ -8,11 +8,7 @@ CFLAGS+= -I${KRB5DIR}/kdc \ -I${KRB5DIR}/lib/ipc \ -I${KRB5DIR}/lib/wind \ -I${KRB5DIR}/lib/roken -DPADD= ${LIBHDB} ${LIBKDC} ${LIBHEIMIPCS} ${LIBKRB5} ${LIBROKEN} ${LIBASN1} \ - ${LIBCRYPTO} ${LIBCRYPT} ${LIBVERS} -LDADD= -lhdb -lkdc ${LDHEIMIPCS} -lkrb5 -lroken -lasn1 -lcrypto -lcrypt \ - ${LIBVERS} -lheimntlm -USEPRIVATELIB= heimipcs +LIBADD= hdb kdc heimipcs krb5 roken asn1 crypto vers heimntlm .include diff --git a/kerberos5/libexec/hprop/Makefile b/kerberos5/libexec/hprop/Makefile index ac1dffa81a65..88f3dadcff71 100644 --- a/kerberos5/libexec/hprop/Makefile +++ b/kerberos5/libexec/hprop/Makefile @@ -10,10 +10,9 @@ CFLAGS+=-I${KRB5DIR}/lib/hx509 CFLAGS+=-I${KRB5DIR}/lib/ntlm CFLAGS+=-I${KRB5DIR}/kdc CFLAGS+=-I${.OBJDIR}/../../lib/libkrb5 -DPADD= ${LIBHDB} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} ${LDAPDPADD} -LDADD= -lhdb -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err ${LDAPLDADD} +LIBADD= hdb krb5 roken vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/libexec/hpropd/Makefile b/kerberos5/libexec/hpropd/Makefile index e0722bd38640..9f7f9e712838 100644 --- a/kerberos5/libexec/hpropd/Makefile +++ b/kerberos5/libexec/hpropd/Makefile @@ -4,10 +4,9 @@ PROG= hpropd MAN= hpropd.8 CFLAGS+=-I${KRB5DIR}/lib/roken -I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/kdc ${LDAPCFLAGS} -DPADD= ${LIBHDB} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} ${LDAPDPADD} -LDADD= -lhdb -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err ${LDAPLDADD} +LIBADD= hdb krb5 roken vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/libexec/ipropd-master/Makefile b/kerberos5/libexec/ipropd-master/Makefile index 99a4f9c3ca30..53e6adebf5fb 100644 --- a/kerberos5/libexec/ipropd-master/Makefile +++ b/kerberos5/libexec/ipropd-master/Makefile @@ -5,10 +5,9 @@ MAN= iprop.8 SRCS= ipropd_common.c ipropd_master.c kadm5_err.h CFLAGS+=-I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/roken \ -I. ${LDAPCFLAGS} -DPADD= ${LIBKADM5SRV} ${LIBHDB} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} ${LDAPDPADD} -LDADD= -lkadm5srv -lhdb -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err ${LDAPLDADD} +LIBADD= kadm5srv hdb krb5 roken vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} foo:: diff --git a/kerberos5/libexec/ipropd-slave/Makefile b/kerberos5/libexec/ipropd-slave/Makefile index 8a72d9e8b2e2..cae84aa5ffb5 100644 --- a/kerberos5/libexec/ipropd-slave/Makefile +++ b/kerberos5/libexec/ipropd-slave/Makefile @@ -5,10 +5,9 @@ MAN= SRCS= ipropd_common.c ipropd_slave.c kadm5_err.h CFLAGS+=-I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/roken \ -I. ${LDAPCFLAGS} -DPADD= ${LIBKADM5SRV} ${LIBHDB} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} ${LDAPDPADD} -LDADD= -lkadm5srv -lhdb -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err ${LDAPLDADD} +LIBADD= kadm5srv hdb krb5 roken vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/libexec/kadmind/Makefile b/kerberos5/libexec/kadmind/Makefile index f88ac2f1b330..27200d6d98ca 100644 --- a/kerberos5/libexec/kadmind/Makefile +++ b/kerberos5/libexec/kadmind/Makefile @@ -9,10 +9,9 @@ SRCS= rpc.c \ CFLAGS+=-I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/roken \ ${LDAPCFLAGS} -DPADD= ${LIBKADM5SRV} ${LIBGSSAPI} ${LIBHDB} ${LIBKRB5} ${LIBROKEN} \ - ${LIBASN1} ${LIBVERS} ${LIBCRYPTO} ${LIBCRYPT} ${LDAPDPADD} -LDADD= -lkadm5srv -lgssapi -lhdb -lkrb5 -lroken \ - -lasn1 ${LIBVERS} -lcrypto -lcrypt ${LDAPLDADD} +LIBADD= kadm5srv gssapi hdb krb5 roken vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/libexec/kcm/Makefile b/kerberos5/libexec/kcm/Makefile index c0e15447ab38..fa7a0cfce9cf 100644 --- a/kerberos5/libexec/kcm/Makefile +++ b/kerberos5/libexec/kcm/Makefile @@ -19,11 +19,9 @@ SRCS= acl.c \ CFLAGS+=-I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/kcm -I${KRB5DIR}/lib/ipc ${LDAPCFLAGS} -DPADD= ${LIBHDB} ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBHEIMNTLM} \ - ${LIBHEIMIPCS} ${LIBCRYPTO} ${LIBCRYPT} ${LIBVERS} ${LDAPDPADD} -LDADD= -lhdb -lkrb5 -lroken -lasn1 -lheimntlm ${LDHEIMIPCS} \ - -lcrypto -lcrypt ${LIBVERS} ${LDAPLDADD} -USEPRIVATELIB= heimipcs +LIBADD= krb5 roken heimntlm heimipcs crypto +DPADD= ${LDAPDPADD} +LDADD= ${LIBVERS} ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/libexec/kdc/Makefile b/kerberos5/libexec/kdc/Makefile index 4ca5c3a201b2..c88a5cd7040e 100644 --- a/kerberos5/libexec/kdc/Makefile +++ b/kerberos5/libexec/kdc/Makefile @@ -10,9 +10,7 @@ SRCS= config.c \ CFLAGS+=-I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/kdc ${LDAPCFLAGS} -DPADD= ${LIBKDC} ${LIBHDB} ${LIBKRB5} ${LIBROKEN} ${LIBASN1} \ - ${LIBCRYPTO} ${LIBCRYPT} ${LIBVERS} -LDADD= -lkdc -lhdb -lkrb5 -lroken -lasn1 -lcrypto -lcrypt ${LIBVERS} +LIBADD= kdc hdb krb5 roken crypt vers .include diff --git a/kerberos5/libexec/kdigest/Makefile b/kerberos5/libexec/kdigest/Makefile index c88e3b990f0f..f9b42e56851e 100644 --- a/kerberos5/libexec/kdigest/Makefile +++ b/kerberos5/libexec/kdigest/Makefile @@ -5,10 +5,7 @@ MAN= kdigest.8 CFLAGS+= -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl -I. -DPADD= ${LIBKRB5} ${LIBHEIMNTLM} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBSL} ${LIBVERS} ${LIBEDIT} -LDADD= -lkrb5 -lheimntlm -lroken -lasn1 -lcrypto -lcrypt ${LIBSL} \ - ${LIBVERS} -ledit +LIBADD= krb5 heimntlm roken crypto edit sl vers SRCS= kdigest.c \ kdigest-commands.c \ kdigest-commands.h diff --git a/kerberos5/libexec/kfd/Makefile b/kerberos5/libexec/kfd/Makefile index f5081f18bed2..82df3adbb6da 100644 --- a/kerberos5/libexec/kfd/Makefile +++ b/kerberos5/libexec/kfd/Makefile @@ -4,10 +4,7 @@ PROG= kfd MAN= kfd.8 CFLAGS+= -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken -DPADD= ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBVERS} -LDADD= -lkrb5 -lroken -lasn1 -lcrypto -lcrypt \ - ${LIBVERS} +LIBADD= krb5 roken vers .include diff --git a/kerberos5/libexec/kimpersonate/Makefile b/kerberos5/libexec/kimpersonate/Makefile index 32f97772c9b5..3c94db6857d0 100644 --- a/kerberos5/libexec/kimpersonate/Makefile +++ b/kerberos5/libexec/kimpersonate/Makefile @@ -6,10 +6,7 @@ CFLAGS+= -I${KRB5DIR}/lib/hx509 \ -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl -I. -DPADD= ${LIBKAFS5} ${LIBKRB5} ${LIBHEIMNTLM} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBVERS} -LDADD= -lkafs5 -lkrb5 -lheimntlm -lroken -lasn1 -lcrypto -lcrypt \ - ${LIBVERS} +LIBADD= krb5 roken asn1 vers .include diff --git a/kerberos5/libexec/kpasswdd/Makefile b/kerberos5/libexec/kpasswdd/Makefile index 22876861edaa..2fe79646aae6 100644 --- a/kerberos5/libexec/kpasswdd/Makefile +++ b/kerberos5/libexec/kpasswdd/Makefile @@ -3,10 +3,9 @@ PROG= kpasswdd MAN= kpasswdd.8 CFLAGS+=-I${KRB5DIR}/lib/roken -I../../lib/libhdb ${LDAPCFLAGS} -DPADD= ${LIBKADM5SRV} ${LIBHDB} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} ${LDAPDPADD} -LDADD= -lkadm5srv -lhdb -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err ${LDAPLDADD} +LIBADD= kadm5srv hdb krb5 roken vers asn1 +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/tools/asn1_compile/Makefile b/kerberos5/tools/asn1_compile/Makefile index 88224da89eff..54c2fdf81967 100644 --- a/kerberos5/tools/asn1_compile/Makefile +++ b/kerberos5/tools/asn1_compile/Makefile @@ -3,8 +3,9 @@ PROG= asn1_compile MAN= LIBROKEN_A= ${.OBJDIR}/../../lib/libroken/libroken.a -LDADD= ${LIBROKEN_A} ${LIBVERS} -DPADD= ${LIBROKEN_A} ${LIBVERS} +LIBADD= vers +LDADD= ${LIBROKEN_A} +DPADD= ${LIBROKEN_A} SRCS= \ asn1parse.y \ diff --git a/kerberos5/tools/slc/Makefile b/kerberos5/tools/slc/Makefile index 1a26e7cd7959..cabd5893884c 100644 --- a/kerberos5/tools/slc/Makefile +++ b/kerberos5/tools/slc/Makefile @@ -2,8 +2,9 @@ PROG= slc LIBROKEN_A= ${.OBJDIR}/../../lib/libroken/libroken.a -LDADD= ${LIBROKEN_A} ${LIBVERS} -DPADD= ${LIBROKEN_A} ${LIBVERS} +LIBADD= vers +LDADD= ${LIBROKEN_A} +DPADD= ${LIBROKEN_A} MAN= SRCS= roken.h \ diff --git a/kerberos5/usr.bin/hxtool/Makefile b/kerberos5/usr.bin/hxtool/Makefile index 3946484b78a1..53612fd1274f 100644 --- a/kerberos5/usr.bin/hxtool/Makefile +++ b/kerberos5/usr.bin/hxtool/Makefile @@ -6,8 +6,7 @@ CFLAGS+= -I${KRB5DIR}/lib/hx509 \ -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl -I. -DPADD= ${LIBHX509} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBSL} ${LIBVERS} ${LIBEDIT} -LDADD= -lhx509 -lroken -lasn1 -lcrypto -lcrypt ${LIBSL} ${LIBVERS} -ledit +LIBADD= hx509 roken asn1 crypto sl vers edit SRCS= hxtool.c hxtool-commands.c hxtool-commands.h hxtool-commands.h: hxtool-commands.in diff --git a/kerberos5/usr.bin/kadmin/Makefile b/kerberos5/usr.bin/kadmin/Makefile index 8ea3efc01564..b3b84b9ab0ce 100644 --- a/kerberos5/usr.bin/kadmin/Makefile +++ b/kerberos5/usr.bin/kadmin/Makefile @@ -26,14 +26,9 @@ SRCS= add_enctype.c \ CFLAGS+=-I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl -I. ${LDAPCFLAGS} -DPADD= ${LIBKADM5CLNT} ${LIBKADM5SRV} ${LIBHDB} ${LIBKRB5} ${LIBHX509} \ - ${LIBSL} ${LIBROKEN} ${LIBVERS} ${LIBASN1} \ - ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} \ - ${LIBEDIT} ${LIBNCURSESW} ${LDAPDPADD} -LDADD= -lkadm5clnt -lkadm5srv -lhdb -lkrb5 -lhx509 \ - ${LIBSL} -lroken ${LIBVERS} -lasn1 \ - -lcrypto -lcrypt -lcom_err \ - -ledit -lncursesw ${LDAPLDADD} +LIBADD= kadm5clnt kadm5srv hdb krb5 roken vers sl asn1 crypto edit +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/usr.bin/kcc/Makefile b/kerberos5/usr.bin/kcc/Makefile index 3da43d7a35b2..cde73f5f7f9e 100644 --- a/kerberos5/usr.bin/kcc/Makefile +++ b/kerberos5/usr.bin/kcc/Makefile @@ -8,10 +8,7 @@ CFLAGS+= -I${KRB5DIR}/lib/hx509 \ -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl -I. -DPADD= ${LIBKRB5} ${LIBHEIMNTLM} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBKAFS5} ${LIBSL} ${LIBVERS} ${LIBEDIT} -LDADD= -lkrb5 -lheimntlm -lroken -lasn1 -lcrypto -lcrypt -lkafs5 ${LIBSL} \ - ${LIBVERS} -ledit +LIBADD= krb5 roken asn1 kafs5 edit sl vers SRCS= kcc.c \ kcc-commands.c \ kcc-commands.h \ diff --git a/kerberos5/usr.bin/kdestroy/Makefile b/kerberos5/usr.bin/kdestroy/Makefile index b3946e42fd29..23e90237c658 100644 --- a/kerberos5/usr.bin/kdestroy/Makefile +++ b/kerberos5/usr.bin/kdestroy/Makefile @@ -2,10 +2,7 @@ PROG= kdestroy CFLAGS+=-I${KRB5DIR}/lib/roken -DPADD= ${LIBKAFS5} ${LIBKRB5} ${LIBHEIMNTLM} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} -LDADD= -lkafs5 -lkrb5 -lheimntlm -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt +LIBADD= kafs5 krb5 roken vers MAN= kdestroy.1 .include diff --git a/kerberos5/usr.bin/kf/Makefile b/kerberos5/usr.bin/kf/Makefile index c9d3fceb14f8..44d91830baaf 100644 --- a/kerberos5/usr.bin/kf/Makefile +++ b/kerberos5/usr.bin/kf/Makefile @@ -4,10 +4,7 @@ PROG= kf MAN= kf.1 CFLAGS+= -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken -DPADD= ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBVERS} -LDADD= -lkrb5 -lroken -lasn1 -lcrypto -lcrypt \ - ${LIBVERS} +LIBADD= krb5 roken vers .include diff --git a/kerberos5/usr.bin/kgetcred/Makefile b/kerberos5/usr.bin/kgetcred/Makefile index dac38adcc18a..1451154f9cf8 100644 --- a/kerberos5/usr.bin/kgetcred/Makefile +++ b/kerberos5/usr.bin/kgetcred/Makefile @@ -3,8 +3,7 @@ PROG= kgetcred CFLAGS+= -I${KRB5DIR}/lib/asn1 \ -I${KRB5DIR}/lib/roken -DPADD= ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBVERS} -LDADD= -lkrb5 -lroken -lasn1 -lcrypto -lcrypt ${LIBVERS} +LIBADD= krb5 roken asn1 vers .include diff --git a/kerberos5/usr.bin/kinit/Makefile b/kerberos5/usr.bin/kinit/Makefile index e0229f98079d..7622b8da956e 100644 --- a/kerberos5/usr.bin/kinit/Makefile +++ b/kerberos5/usr.bin/kinit/Makefile @@ -2,10 +2,7 @@ PROG= kinit CFLAGS+=-I${KRB5DIR}/lib/roken -DPADD= ${LIBKAFS5} ${LIBKRB5} ${LIBHEIMNTLM} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} -LDADD= -lkafs5 -lkrb5 -lheimntlm -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err +LIBADD= kafs5 krb5 heimntlm roken crypto vers .include diff --git a/kerberos5/usr.bin/kpasswd/Makefile b/kerberos5/usr.bin/kpasswd/Makefile index a9ab1c99ec89..66cb4569a650 100644 --- a/kerberos5/usr.bin/kpasswd/Makefile +++ b/kerberos5/usr.bin/kpasswd/Makefile @@ -2,10 +2,7 @@ PROG= kpasswd CFLAGS+=-I${KRB5DIR}/lib/roken -DPADD= ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} -LDADD= -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err +LIBADD= hdb krb5 roken vers crypto .include diff --git a/kerberos5/usr.bin/ksu/Makefile b/kerberos5/usr.bin/ksu/Makefile index 9e2786577ff8..ebd39c677b54 100644 --- a/kerberos5/usr.bin/ksu/Makefile +++ b/kerberos5/usr.bin/ksu/Makefile @@ -8,10 +8,7 @@ PRECIOUSPROG= MAN= SRCS= su.c CFLAGS+=-I${KRB5DIR}/lib/roken -DPADD= ${LIBKAFS5} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} -LDADD= -lkafs5 -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err +LIBADD= kafs5 krb5 roken vers crypto crypt .include diff --git a/kerberos5/usr.bin/string2key/Makefile b/kerberos5/usr.bin/string2key/Makefile index fc790e24dd88..eb7b2043fac0 100644 --- a/kerberos5/usr.bin/string2key/Makefile +++ b/kerberos5/usr.bin/string2key/Makefile @@ -7,9 +7,7 @@ CFLAGS+= -I${KRB5DIR}/kdc \ -I${KRB5DIR}/lib/krb5 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/windc -DPADD= ${LIBHDB} ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBVERS} -LDADD= -lhdb -lkrb5 -lroken -lasn1 -lcrypto -lcrypt ${LIBVERS} +LIBADD= krb5 roken crypto vers .include diff --git a/kerberos5/usr.bin/verify_krb5_conf/Makefile b/kerberos5/usr.bin/verify_krb5_conf/Makefile index 830e66a29115..ced75436e523 100644 --- a/kerberos5/usr.bin/verify_krb5_conf/Makefile +++ b/kerberos5/usr.bin/verify_krb5_conf/Makefile @@ -3,10 +3,7 @@ PROG= verify_krb5_conf MAN= verify_krb5_conf.8 CFLAGS+=-I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/roken -DPADD= ${LIBKAFS5} ${LIBKRB5} ${LIBHX509} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBCOM_ERR} -LDADD= -lkafs5 -lkrb5 -lhx509 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -lcom_err +LIBADD= krb5 roken vers .include diff --git a/kerberos5/usr.sbin/iprop-log/Makefile b/kerberos5/usr.sbin/iprop-log/Makefile index 176012a9e7d9..f31be516fb28 100644 --- a/kerberos5/usr.sbin/iprop-log/Makefile +++ b/kerberos5/usr.sbin/iprop-log/Makefile @@ -8,10 +8,7 @@ CFLAGS+= -I${KRB5DIR}/lib/kadm5 \ -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/lib/sl \ -I. -DPADD= ${LIBKADM5SRV} ${LIBHDB} ${LIBKRB5} ${LIBASN1} ${LIBCRYPTO} \ - ${LIBCRYPT} ${LIBSL} ${LIBROKEN} ${LIBVERS} ${LIBEDIT} -LDADD= -lkadm5srv -lhdb -lkrb5 -lasn1 -lcrypto -lcrypt ${LIBSL} -lroken \ - ${LIBVERS} -ledit +LIBADD= kadm5srv hdb krb5 roken edit sl vers iprop-commands.h: iprop-commands.in ${SLC} ${.ALLSRC:M*.in} diff --git a/kerberos5/usr.sbin/kstash/Makefile b/kerberos5/usr.sbin/kstash/Makefile index 024e45dba917..d96c96c75121 100644 --- a/kerberos5/usr.sbin/kstash/Makefile +++ b/kerberos5/usr.sbin/kstash/Makefile @@ -4,10 +4,9 @@ PROG= kstash MAN= kstash.8 CFLAGS+=-I${KRB5DIR}/lib/asn1 -I${KRB5DIR}/lib/krb5 -I${KRB5DIR}/lib/roken \ -I${KRB5DIR}/kdc ${LDAPCFLAGS} -DPADD= ${LIBHDB} ${LIBKRB5} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LDAPDPADD} -LDADD= -lhdb -lkrb5 -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt ${LDAPLDADD} +LIBADD= hdb krb5 crypto vers +DPADD= ${LDAPDPADD} +LDADD= ${LDAPLDADD} LDFLAGS=${LDAPLDFLAGS} .include diff --git a/kerberos5/usr.sbin/ktutil/Makefile b/kerberos5/usr.sbin/ktutil/Makefile index f7d340f78e9a..fe45494c40cb 100644 --- a/kerberos5/usr.sbin/ktutil/Makefile +++ b/kerberos5/usr.sbin/ktutil/Makefile @@ -17,10 +17,7 @@ SRCS= add.c \ rename.c CFLAGS+=-I${KRB5DIR}/lib/roken -I${KRB5DIR}/lib/sl -I. -DPADD= ${LIBKADM5CLNT} ${LIBKRB5} ${LIBSL} ${LIBROKEN} ${LIBVERS} \ - ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} ${LIBEDIT} -LDADD= -lkadm5clnt -lkrb5 ${LIBSL} -lroken ${LIBVERS} \ - -lasn1 -lcrypto -lcrypt -ledit +LIBADD= kadm5clnt krb5 roken crypto edit sl vers .include diff --git a/lib/Makefile b/lib/Makefile index 958721d37bb1..b25a72f30db7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -52,6 +52,7 @@ SUBDIR= ${SUBDIR_ORDERED} \ libfigpar \ libgeom \ ${_libgpib} \ + libgpio \ ${_libgssapi} \ ${_librpcsec_gss} \ ${_libiconv_modules} \ diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile index 352a8f4caa4d..c8fdfacf3686 100644 --- a/lib/atf/libatf-c++/Makefile +++ b/lib/atf/libatf-c++/Makefile @@ -33,8 +33,7 @@ PRIVATELIB= true SHLIB_MAJOR= 2 # libatf-c++ depends on the C version of the ATF library to build. -DPADD= ${LIBATF_C} -LDADD= -latf-c +LIBADD+= atf_c LDFLAGS+= -L${.OBJDIR}/../libatf-c diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile index b7e9d7fc95fe..2542a2053e01 100644 --- a/lib/libarchive/Makefile +++ b/lib/libarchive/Makefile @@ -4,19 +4,9 @@ LIBARCHIVEDIR= ${.CURDIR}/../../contrib/libarchive LIB= archive -DPADD= ${LIBZ} -LDADD= -lz -DPADD+= ${LIBBZ2} -LDADD+= -lbz2 -CFLAGS+= -DHAVE_BZLIB_H=1 - -DPADD+= ${LIBLZMA} -LDADD+= -llzma -CFLAGS+= -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1 - -DPADD+= ${LIBBSDXML} -LDADD+= -lbsdxml +LIBADD= z bz2 lzma bsdxml +CFLAGS+= -DHAVE_BZLIB_H=1 -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1 # FreeBSD SHLIB_MAJOR value is managed as part of the FreeBSD system. # It has no real relation to the libarchive version number. @@ -27,11 +17,9 @@ CFLAGS+= -I${.OBJDIR} .if ${MK_OPENSSL} != "no" CFLAGS+= -DWITH_OPENSSL -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto .else -DPADD+= ${LIBMD} -LDADD+= -lmd +LIBADD+= md .endif .if ${MK_ICONV} != "no" diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile index 16a485ae2c44..80d6dd4a03ff 100644 --- a/lib/libarchive/test/Makefile +++ b/lib/libarchive/test/Makefile @@ -6,9 +6,8 @@ MAN= PROG=libarchive_test INTERNALPROG=yes # Don't install this; it's just for testing -DPADD=${LIBBZ2} ${LIBZ} ${LIBMD} ${LIBCRYPTO} ${LIBBSDXML} LDADD= -L ${.OBJDIR}/.. -larchive -LDADD+= -lz -lbz2 -llzma -lmd -lcrypto -lbsdxml +LIBADD= z bz2 lzma md crypto bsdxml CFLAGS+= -g CFLAGS+= -I${.CURDIR}/.. -I${.OBJDIR} CFLAGS+= -I${LIBARCHIVEDIR}/libarchive -I${LIBARCHIVEDIR}/test_utils diff --git a/lib/libbsnmp/libbsnmp/Makefile b/lib/libbsnmp/libbsnmp/Makefile index 0b9087d6540c..cc294cf57eee 100644 --- a/lib/libbsnmp/libbsnmp/Makefile +++ b/lib/libbsnmp/libbsnmp/Makefile @@ -15,8 +15,7 @@ CFLAGS+= -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DQUADFMT='"llu"' -DQUADXFMT='"llx"' .if ${MK_OPENSSL} != "no" CFLAGS+= -DHAVE_LIBCRYPTO -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD= crypto .endif SRCS= asn1.c snmp.c snmpagent.c snmpclient.c snmpcrypto.c support.c diff --git a/lib/libc++/Makefile b/lib/libc++/Makefile index e55cf55a5d8f..4a849b042d07 100644 --- a/lib/libc++/Makefile +++ b/lib/libc++/Makefile @@ -62,8 +62,7 @@ CFLAGS+= -I${HDRDIR} -I${LIBCXXRTDIR} -nostdlib -DLIBCXXRT CXXFLAGS+= -std=c++11 .endif -DPADD= ${LIBCXXRT} -LDADD= -lcxxrt +LIBADD+= cxxrt LDFLAGS+= --verbose INCSGROUPS= STD EXP EXT diff --git a/lib/libc/Makefile b/lib/libc/Makefile index a535edfedf28..9853d4b707c3 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -44,13 +44,11 @@ CFLAGS+=${CANCELPOINTS_CFLAGS} # # Link with static libcompiler_rt.a. # -DPADD+= ${LIBCOMPILER_RT} LDFLAGS+= -nodefaultlibs -LDADD+= -lcompiler_rt +LIBADD+= compiler_rt .if ${MK_SSP} != "no" -DPADD+= ${LIBSSP_NONSHARED} -LDADD+= -lssp_nonshared +LIBADD+= ssp_nonshared .endif # Extras that live in either libc.a or libc_nonshared.a diff --git a/lib/libc/gen/errlst.c b/lib/libc/gen/errlst.c index 12d9f8bfbd68..f8fe9684a26a 100644 --- a/lib/libc/gen/errlst.c +++ b/lib/libc/gen/errlst.c @@ -158,7 +158,7 @@ const char *const sys_errlist[] = { }; const int sys_nerr = sizeof(sys_errlist) / sizeof(sys_errlist[0]); -#ifdef __PIC__ +#ifdef PIC __strong_reference(sys_errlist, __hidden_sys_errlist); __strong_reference(sys_nerr, __hidden_sys_nerr); #endif diff --git a/lib/libc/gen/isnan.c b/lib/libc/gen/isnan.c index 0eb7372ef59a..72c2868b5e90 100644 --- a/lib/libc/gen/isnan.c +++ b/lib/libc/gen/isnan.c @@ -40,7 +40,7 @@ * time, when calling both functions. */ -#ifdef __PIC__ +#ifdef PIC __weak_reference(__isnan, isnan); __weak_reference(__isnanf, isnanf); @@ -61,4 +61,4 @@ __isnanf(float f) u.f = f; return (u.bits.exp == 255 && u.bits.man != 0); } -#endif /* __PIC__ */ +#endif /* PIC */ diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c index 3a5cafec51c2..003f24ddcaf6 100644 --- a/lib/libc/gen/syslog.c +++ b/lib/libc/gen/syslog.c @@ -261,26 +261,45 @@ vsyslog(int pri, const char *fmt, va_list ap) connectlog(); /* - * If the send() failed, there are two likely scenarios: + * If the send() fails, there are two likely scenarios: * 1) syslogd was restarted * 2) /var/run/log is out of socket buffer space, which * in most cases means local DoS. - * We attempt to reconnect to /var/run/log[priv] to take care of - * case #1 and keep send()ing data to cover case #2 - * to give syslogd a chance to empty its socket buffer. + * If the error does not indicate a full buffer, we address + * case #1 by attempting to reconnect to /var/run/log[priv] + * and resending the message once. * - * If we are working with a priveleged socket, then take - * only one attempt, because we don't want to freeze a + * If we are working with a privileged socket, the retry + * attempts end there, because we don't want to freeze a * critical application like su(1) or sshd(8). * + * Otherwise, we address case #2 by repeatedly retrying the + * send() to give syslogd a chance to empty its socket buffer. */ if (send(LogFile, tbuf, cnt, 0) < 0) { if (errno != ENOBUFS) { + /* + * Scenario 1: syslogd was restarted + * reconnect and resend once + */ disconnectlog(); connectlog(); + if (send(LogFile, tbuf, cnt, 0) >= 0) { + THREAD_UNLOCK(); + return; + } + /* + * if the resend failed, fall through to + * possible scenario 2 + */ } - do { + while (errno == ENOBUFS) { + /* + * Scenario 2: out of socket buffer space + * possible DoS, fail fast on a privileged + * socket + */ if (status == CONNPRIV) break; _usleep(1); @@ -288,7 +307,7 @@ vsyslog(int pri, const char *fmt, va_list ap) THREAD_UNLOCK(); return; } - } while (errno == ENOBUFS); + } } else { THREAD_UNLOCK(); return; @@ -350,7 +369,7 @@ connectlog(void) SyslogAddr.sun_family = AF_UNIX; /* - * First try priveleged socket. If no success, + * First try privileged socket. If no success, * then try default socket. */ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV, diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c index 96b15ec2b7d6..5219418fdc32 100644 --- a/lib/libc/gen/tls.c +++ b/lib/libc/gen/tls.c @@ -78,7 +78,7 @@ void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign); #define TLS_VARIANT_II #endif -#ifndef __PIC__ +#ifndef PIC #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) @@ -107,7 +107,7 @@ __libc_tls_get_addr(void *ti __unused) return (0); } -#ifndef __PIC__ +#ifndef PIC #ifdef TLS_VARIANT_I @@ -264,14 +264,14 @@ __libc_free_tls(void *tcb __unused, size_t tcbsize __unused, { } -#endif /* __PIC__ */ +#endif /* PIC */ extern char **environ; void _init_tls() { -#ifndef __PIC__ +#ifndef PIC Elf_Addr *sp; Elf_Auxinfo *aux, *auxp; Elf_Phdr *phdr; diff --git a/lib/libc/include/errlst.h b/lib/libc/include/errlst.h index 1b329b311bde..4e9e29fc3345 100644 --- a/lib/libc/include/errlst.h +++ b/lib/libc/include/errlst.h @@ -31,7 +31,7 @@ #include -#ifdef __PIC__ +#ifdef PIC /* If the main executable imports these, do not use its copy from libc.so. */ extern const char *const __hidden_sys_errlist[] __hidden; extern const int __hidden_sys_nerr __hidden; diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c index 43350303898e..8a9c59e3142d 100644 --- a/lib/libc/net/base64.c +++ b/lib/libc/net/base64.c @@ -193,12 +193,10 @@ b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { */ int -b64_pton(src, target, targsize) - char const *src; - u_char *target; - size_t targsize; +b64_pton(const char *src, u_char *target, size_t targsize) { int tarindex, state, ch; + u_char nextbyte; char *pos; state = 0; @@ -226,22 +224,28 @@ b64_pton(src, target, targsize) break; case 1: if (target) { - if ((size_t)tarindex + 1 >= targsize) + if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; - target[tarindex+1] = ((pos - Base64) & 0x0f) - << 4 ; + nextbyte = ((pos - Base64) & 0x0f) << 4; + if ((size_t)tarindex + 1 < targsize) + target[tarindex + 1] = nextbyte; + else if (nextbyte) + return (-1); } tarindex++; state = 2; break; case 2: if (target) { - if ((size_t)tarindex + 1 >= targsize) + if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; - target[tarindex+1] = ((pos - Base64) & 0x03) - << 6; + nextbyte = ((pos - Base64) & 0x03) << 6; + if ((size_t)tarindex + 1 < targsize) + target[tarindex + 1] = nextbyte; + else if (nextbyte) + return (-1); } tarindex++; state = 3; @@ -299,7 +303,8 @@ b64_pton(src, target, targsize) * zeros. If we don't check them, they become a * subliminal channel. */ - if (target && target[tarindex] != 0) + if (target && (size_t)tarindex < targsize && + target[tarindex] != 0) return (-1); } } else { diff --git a/lib/libc/net/getifaddrs.3 b/lib/libc/net/getifaddrs.3 index ff3f77493a77..b0b17bb388da 100644 --- a/lib/libc/net/getifaddrs.3 +++ b/lib/libc/net/getifaddrs.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 21, 2013 +.Dd November 25, 2014 .Dt GETIFADDRS 3 .Os .Sh NAME @@ -110,19 +110,17 @@ if one exists, otherwise it is NULL. .Pp The .Li ifa_data -field references address family specific data. -For -.Dv AF_LINK -addresses it contains a pointer to the +field references address family specific data +in a pointer to the .Fa struct if_data (as defined in include file -.In net/if.h ) -which contains various interface attributes and statistics. -For all other address families, it contains a pointer to the -.Fa struct ifa_data -(as defined in include file -.In net/if.h ) -which contains per-address interface statistics. +.In net/if.h ) . +For +.Dv AF_LINK +addresses, +it contains various interface attributes and statistics. +For all other address families, +it contains per-address interface statistics. .Pp The data returned by .Fn getifaddrs diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index c23315cbd108..4de1df3ffd16 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -132,14 +132,17 @@ static void *nss_cache_cycle_prevention_func = NULL; #endif /* - * When this is set to 1, nsdispatch won't use nsswitch.conf - * but will consult the 'defaults' source list only. - * NOTE: nested fallbacks (when nsdispatch calls fallback functions, - * which in turn calls nsdispatch, which should call fallback - * function) are not supported + * We keep track of nsdispatch() nesting depth in dispatch_depth. When a + * fallback method is invoked from nsdispatch(), we temporarily set + * fallback_depth to the current dispatch depth plus one. Subsequent + * calls at that exact depth will run in fallback mode (restricted to the + * same source as the call that was handled by the fallback method), while + * calls below that depth will be handled normally, allowing fallback + * methods to perform arbitrary lookups. */ struct fb_state { - int fb_dispatch; + int dispatch_depth; + int fallback_depth; }; static void fb_endstate(void *); NSS_TLS_HANDLING(fb); @@ -613,6 +616,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, void *mdata; int isthreaded, serrno, i, result, srclistsize; struct fb_state *st; + int saved_depth; #ifdef NS_CACHING nss_cache_data cache_data; @@ -644,7 +648,8 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, result = NS_UNAVAIL; goto fin; } - if (st->fb_dispatch == 0) { + ++st->dispatch_depth; + if (st->dispatch_depth > st->fallback_depth) { dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); fb_method = nss_method_lookup(NSSRC_FALLBACK, database, @@ -713,12 +718,13 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, break; } else { if (fb_method != NULL) { - st->fb_dispatch = 1; + saved_depth = st->fallback_depth; + st->fallback_depth = st->dispatch_depth + 1; va_start(ap, defaults); result = fb_method(retval, (void *)srclist[i].name, ap); va_end(ap); - st->fb_dispatch = 0; + st->fallback_depth = saved_depth; } else nss_log(LOG_DEBUG, "%s, %s, %s, not found, " "and no fallback provided", @@ -750,6 +756,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, if (isthreaded) (void)_pthread_rwlock_unlock(&nss_lock); + --st->dispatch_depth; fin: errno = serrno; return (result); diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c index 6ce2a2513655..ed7d6352337e 100644 --- a/lib/libc/sys/stack_protector.c +++ b/lib/libc/sys/stack_protector.c @@ -115,6 +115,6 @@ __chk_fail(void) __fail("buffer overflow detected; terminated"); } -#ifndef __PIC__ +#ifndef PIC __weak_reference(__stack_chk_fail, __stack_chk_fail_local); #endif diff --git a/lib/libc/sys/stack_protector_compat.c b/lib/libc/sys/stack_protector_compat.c index 888eb5ed4e42..cacb863e75e6 100644 --- a/lib/libc/sys/stack_protector_compat.c +++ b/lib/libc/sys/stack_protector_compat.c @@ -8,7 +8,7 @@ __FBSDID("$FreeBSD$"); void __stack_chk_fail(void); -#ifdef __PIC__ +#ifdef PIC void __stack_chk_fail_local_hidden(void) { diff --git a/lib/libcam/Makefile b/lib/libcam/Makefile index 1621fe62cf16..c44836947d51 100644 --- a/lib/libcam/Makefile +++ b/lib/libcam/Makefile @@ -6,8 +6,7 @@ SRCS= camlib.c scsi_cmdparse.c scsi_all.c scsi_da.c scsi_sa.c cam.c \ ata_all.c smp_all.c INCS= camlib.h -DPADD= ${LIBSBUF} -LDADD= -lsbuf +LIBADD= sbuf MAN= cam.3 cam_cdbparse.3 diff --git a/lib/libcapsicum/Makefile b/lib/libcapsicum/Makefile index 061edfcb9067..6ee5bb83eada 100644 --- a/lib/libcapsicum/Makefile +++ b/lib/libcapsicum/Makefile @@ -21,8 +21,7 @@ INCS+= libcapsicum_random.h INCS+= libcapsicum_service.h INCS+= libcapsicum_sysctl.h -DPADD= ${LIBNV} -LDADD= -lnv +LIBADD= nv CFLAGS+=-I${.CURDIR} CFLAGS+=-I${.CURDIR}/../libnv diff --git a/lib/libcasper/Makefile b/lib/libcasper/Makefile index ddcfba5131b1..e57accdf94a3 100644 --- a/lib/libcasper/Makefile +++ b/lib/libcasper/Makefile @@ -8,8 +8,7 @@ SHLIBDIR?= /lib SRCS= libcasper.c INCS= libcasper.h -DPADD= ${LIBCAPSICUM} ${LIBNV} ${LIBPJDLOG} -LDADD= -lcapsicum -lnv -lpjdlog +LIBADD= capsicum nv pjdlog CFLAGS+=-I${.CURDIR} CFLAGS+=-I${.CURDIR}/../libpjdlog diff --git a/lib/libcrypt/tests/Makefile b/lib/libcrypt/tests/Makefile index 20993e27f3d1..6f98b53a3437 100644 --- a/lib/libcrypt/tests/Makefile +++ b/lib/libcrypt/tests/Makefile @@ -7,7 +7,6 @@ TESTSDIR= ${TESTSBASE}/lib/libcrypt ATF_TESTS_C= crypt_tests CFLAGS+= -I${.CURDIR:H} -DPADD+= ${LIBCRYPT} -LDADD+= -lcrypt +LIBADD= crypt .include diff --git a/lib/libcuse/Makefile b/lib/libcuse/Makefile index 2d1ded51a07e..a232fa241c62 100644 --- a/lib/libcuse/Makefile +++ b/lib/libcuse/Makefile @@ -30,14 +30,12 @@ SHLIB_MINOR= 0 SRCS= cuse_lib.c INCS= cuse.h MAN= cuse.3 -PTHREAD_LIBS?= -lpthread CFLAGS+= -D_GNU_SOURCE .if defined(HAVE_DEBUG) CFLAGS+= -g CFLAGS+= -DHAVE_DEBUG .endif -DPADD+= ${LIBPTHREAD} -LDADD+= ${PTHREAD_LIBS} +LIBADD= pthread MLINKS= MLINKS+= cuse.3 cuse_alloc_unit_number.3 diff --git a/lib/libdevstat/Makefile b/lib/libdevstat/Makefile index aeb07b9f0647..dcda3c2bdac8 100644 --- a/lib/libdevstat/Makefile +++ b/lib/libdevstat/Makefile @@ -7,8 +7,7 @@ SHLIB_MAJOR= 7 SRCS= devstat.c INCS= devstat.h -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm MAN= devstat.3 diff --git a/lib/libdpv/Makefile b/lib/libdpv/Makefile index 8096cc92c8ec..f2dc481057e5 100644 --- a/lib/libdpv/Makefile +++ b/lib/libdpv/Makefile @@ -6,8 +6,7 @@ INCS= dpv.h MAN= dpv.3 MLINKS= dpv.3 dpv_free.3 -DPADD= ${LIBDIALOG} ${LIBFIGPAR} ${LIBNCURSESW} ${LIBUTIL} -LDADD= -ldialog -lfigpar -lncursesw -lutil +LIBADD= dialog figpar util ncursesw SRCS= dialog_util.c dialogrc.c dprompt.c dpv.c status.c util.c diff --git a/lib/libdwarf/Makefile b/lib/libdwarf/Makefile index 9d4df830ff07..890e215a9a84 100644 --- a/lib/libdwarf/Makefile +++ b/lib/libdwarf/Makefile @@ -96,8 +96,7 @@ sys/elf32.h sys/elf64.h sys/elf_common.h: ${.CURDIR}/../../sys/${.TARGET} mkdir -p ${.OBJDIR}/sys ln -sf ${.CURDIR}/../../sys/${.TARGET} ${.TARGET} -LDADD+= -lelf -DPADD+= ${LIBELF} +LIBADD+= elf SHLIB_MAJOR= 4 diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index df86778c5778..6e60a724e198 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -10,8 +10,7 @@ OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \ hist.c key.c map.c \ parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c -DPADD= ${LIBNCURSESW} -LDADD= -lncursesw +LIBADD= ncursesw MAN= editline.3 editrc.5 diff --git a/lib/libexecinfo/Makefile b/lib/libexecinfo/Makefile index 81fa82a44a59..5f9aac5e5c21 100644 --- a/lib/libexecinfo/Makefile +++ b/lib/libexecinfo/Makefile @@ -10,8 +10,7 @@ SHLIB_MAJOR= 1 INCS= execinfo.h SRCS= backtrace.c symtab.c unwind.c -DPADD= ${LIBELF} -LDADD= -lelf +LIBADD= elf MAN= backtrace.3 diff --git a/lib/libfetch/Makefile b/lib/libfetch/Makefile index cef5f5a43c18..4f56552801cf 100644 --- a/lib/libfetch/Makefile +++ b/lib/libfetch/Makefile @@ -16,11 +16,9 @@ CFLAGS+= -DINET6 .if ${MK_OPENSSL} != "no" CFLAGS+= -DWITH_SSL -DPADD= ${LIBSSL} ${LIBCRYPTO} -LDADD= -lssl -lcrypto +LIBADD+= ssl crypto .else -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD+= md .endif CFLAGS+= -DFTP_COMBINE_CWDS diff --git a/lib/libgeom/Makefile b/lib/libgeom/Makefile index b19faf6198ec..20b7a4c7c3b8 100644 --- a/lib/libgeom/Makefile +++ b/lib/libgeom/Makefile @@ -13,8 +13,7 @@ CFLAGS += -I${.CURDIR} WARNS?= 3 -DPADD= ${LIBBSDXML} ${LIBSBUF} -LDADD= -lbsdxml -lsbuf +LIBADD+= bsdxml sbuf MAN= libgeom.3 diff --git a/lib/libgpio/Makefile b/lib/libgpio/Makefile new file mode 100644 index 000000000000..48b71d01a1ab --- /dev/null +++ b/lib/libgpio/Makefile @@ -0,0 +1,35 @@ +# $FreeBSD$ + +LIB= gpio +SHLIB_MAJOR= 0 + +SRCS= gpio.c +INCS= libgpio.h +MAN+= gpio.3 + +CFLAGS+= -I${.CURDIR} + +MLINKS= gpio.3 gpio_open.3 \ + gpio.3 gpio_open_device.3 \ + gpio.3 gpio_close.3 \ + gpio.3 gpio_pin_list.3 \ + gpio.3 gpio_pin_config.3 \ + gpio.3 gpio_pin_set_flags.3 \ + gpio.3 gpio_pin_get.3 \ + gpio.3 gpio_pin_set.3 \ + gpio.3 gpio_pin_low.3 \ + gpio.3 gpio_pin_high.3 \ + gpio.3 gpio_pin_input.3 \ + gpio.3 gpio_pin_output.3 \ + gpio.3 gpio_pin_opendrain.3 \ + gpio.3 gpio_pin_pushpull.3 \ + gpio.3 gpio_pin_tristate.3 \ + gpio.3 gpio_pin_pullup.3 \ + gpio.3 gpio_pin_pulldown.3 \ + gpio.3 gpio_pin_invin.3 \ + gpio.3 gpio_pin_invout.3 \ + gpio.3 gpio_pin_pulsate.3 + +WARNS?= 6 + +.include diff --git a/lib/libgpio/gpio.3 b/lib/libgpio/gpio.3 new file mode 100644 index 000000000000..12b2d1eeed1f --- /dev/null +++ b/lib/libgpio/gpio.3 @@ -0,0 +1,192 @@ +.\" +.\" Copyright (c) 2014 Rui Paulo +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 17, 2014 +.Dt GPIO 3 +.Os +.Sh NAME +.Nm gpio_open , +.Nm gpio_close +.Nd "library to handle GPIO pins" +.Sh LIBRARY +.Lb libgpio +.Sh SYNOPSIS +.In libgpio.h +.Ft "gpio_handle_t" +.Fn gpio_open "unsigned int unit" +.Ft "gpio_handle_t" +.Fn gpio_open_device "const char *device" +.Ft void +.Fn gpio_close "gpio_handle_t handle" +.Ft int +.Fn gpio_pin_list "gpio_handle_t handle, gpio_config_t **pcfgs" +.Ft int +.Fn gpio_pin_config "gpio_handle_t handle, gpio_config *cfg" +.Ft int +.Fn gpio_pin_set_flags "gpio_handle_t handle, gpio_config_t *cfg" +.Ft gpio_value_t +.Fn gpio_pin_get "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_set "gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value" +.Ft int +.Fn gpio_pin_toggle "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_low "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_high "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_input "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_output "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_opendrain "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_pushpull "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_tristate "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_pullup "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_pulldown "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_invin "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_invout "gpio_handle_t handle, gpio_pin_t pin" +.Ft int +.Fn gpio_pin_pulsate "gpio_handle_t handle, gpio_pin_t pin" +.Sh DESCRIPTION +The +.Nm libgpio +library provides an interface to configure GPIO pins. +The library operates with a +.Ft gpio_handle_t +opaque type which can be created with +.Fn gpio_open +or +.Fn gpio_open_device . +When no more GPIO operations are needed, this handle can be destroyed +with +.Fn gpio_close . +.Pp +To get a list of all available pins, one can call +.Fn gpio_pin_list . +This function takes a pointer to a +.Ft gpio_config_t +which is dynamically allocated. +This pointer should be freed with +.Xr free 3 +when it's no longer necessary. +.Pp +The function +.Fn gpio_pin_config +retrieves the current configuration of a pin. +The pin number should be passed in via the +.Ft g_pin +variable which is part of the +.Ft gpio_config_t +structure. +.Pp +The function +.Fn gpio_pin_set_flags +configures a pin with the flags passed in by the +.Ft gpio_config_t +structure. +The pin number should also be passed in through the +.Ft g_pin +variable. +All other structure members will be ignored by this function. +The list of flags can be found in +.Pa /usr/include/sys/gpio.h . +.Pp +The get or set the state of a GPIO pin, the functions +.Fn gpio_pin_get +and +.Fn gpio_pin_set +are available, respectively. +To toggle the state, use +.Fn gpio_pin_toggle . +.Pp +The functions +.Fn gpio_pin_low +and +.Fn gpio_pin_high +are wrappers around +.Fn gpio_pin_set . +.Pp +The functions +.Fn gpio_pin_input , +.Fn gpio_pin_output , +.Fn gpio_pin_opendrain , +.Fn gpio_pin_pushpull , +.Fn gpio_pin_tristate , +.Fn gpio_pin_pullup , +.Fn gpio_pin_pulldown , +.Fn gpio_pin_invin , +.Fn gpio_pin_invout +and +.Fn gpio_pin_pulsate +are wrappers around +.Fn gpio_pin_set_flags . +.Sh EXAMPLES +The following example shows how to configure pin 16 as output and then +drive it high: +.Bd -literal +#include +#include + +gpio_handle_t handle; + +handle = gpio_open(0); +if (handle == GPIO_HANDLE_INVALID) + err(1, "gpio_open failed"); +gpio_pin_output(handle, 16); +gpio_pin_high(handle, 16); +gpio_close(handle); +.Ed +.Pp +The following example shows how to get a configuration of a pin: +.Bd -literal +gpio_config_t cfg; + +cfg.g_pin = 32; +gpio_pin_config(handle, &cfg); +.Ed +.Pp +The structure will contain the name of the pin and its flags. +.Sh SEE ALSO +.Xr gpiobus 4 , +.Xr gpioctl 8 +.Sh HISTORY +The +.Nm libgpio +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm libgpio +library was implemented by +.An Rui Paulo Aq Mt rpaulo@FreeBSD.org . diff --git a/lib/libgpio/gpio.c b/lib/libgpio/gpio.c new file mode 100644 index 000000000000..d22b3cf5392c --- /dev/null +++ b/lib/libgpio/gpio.c @@ -0,0 +1,262 @@ +/*- + * Copyright (c) 2013-2014 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +gpio_handle_t +gpio_open(unsigned int unit) +{ + char device[16]; + + snprintf(device, sizeof(device), "/dev/gpioc%u", unit); + + return (gpio_open_device(device)); +} + +gpio_handle_t +gpio_open_device(const char *device) +{ + int fd, maxpins; + int serr; + + fd = open(device, O_RDONLY); + if (fd < 0) + return (GPIO_INVALID_HANDLE); + /* + * Check whether a simple ioctl works. + */ + if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { + serr = errno; + close(fd); + errno = serr; + return (GPIO_INVALID_HANDLE); + } + + return (fd); +} + +void +gpio_close(gpio_handle_t handle) +{ + close(handle); +} + +int +gpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) +{ + int maxpins, i; + gpio_config_t *cfgs; + + *pcfgs = NULL; + if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) + return (-1); + /* Reasonable values. */ + if (maxpins < 0 || maxpins > 4096) { + errno = EINVAL; + return (-1); + } + cfgs = calloc(maxpins, sizeof(*cfgs)); + if (cfgs == NULL) + return (-1); + for (i = 0; i <= maxpins; i++) { + cfgs[i].g_pin = i; + gpio_pin_config(handle, &cfgs[i]); + } + *pcfgs = cfgs; + + return (maxpins); +} + +int +gpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) +{ + struct gpio_pin gppin; + + if (cfg == NULL) + return (-1); + gppin.gp_pin = cfg->g_pin; + if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) + return (-1); + strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); + cfg->g_caps = gppin.gp_caps; + cfg->g_flags = gppin.gp_flags; + + return (0); +} + +int +gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) +{ + struct gpio_pin gppin; + + if (cfg == NULL) + return (-1); + gppin.gp_pin = cfg->g_pin; + gppin.gp_flags = cfg->g_flags; + if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) + return (-1); + + return (0); +} + +gpio_value_t +gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) +{ + struct gpio_req gpreq; + + bzero(&gpreq, sizeof(gpreq)); + gpreq.gp_pin = pin; + if (ioctl(handle, GPIOGET, &gpreq) < 0) + return (GPIO_VALUE_INVALID); + + return (gpreq.gp_value); +} + +int +gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) +{ + struct gpio_req gpreq; + + if (value == GPIO_VALUE_INVALID) + return (-1); + bzero(&gpreq, sizeof(gpreq)); + gpreq.gp_pin = pin; + gpreq.gp_value = value; + if (ioctl(handle, GPIOSET, &gpreq) < 0) + return (-1); + + return (0); +} + +int +gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) +{ + gpio_value_t value; + + value = gpio_pin_get(handle, pin); + if (value == GPIO_VALUE_INVALID) + return (-1); + value = !value; + + return (gpio_pin_set(handle, pin, value)); +} + +int +gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); +} + +int +gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); +} + +static int +gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) +{ + gpio_config_t cfg; + + bzero(&cfg, sizeof(cfg)); + cfg.g_pin = pin; + if (gpio_pin_config(handle, &cfg) < 0) + return (-1); + cfg.g_flags = flag; + + return (gpio_pin_set_flags(handle, &cfg)); +} + +int +gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); +} + +int +gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); +} + +int +gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); +} + +int +gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); +} + +int +gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); +} + +int +gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); +} + +int +gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); +} + +int +gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); +} + +int +gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); +} + +int +gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) +{ + return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); +} diff --git a/lib/libgpio/libgpio.h b/lib/libgpio/libgpio.h new file mode 100644 index 000000000000..b7486ebc5472 --- /dev/null +++ b/lib/libgpio/libgpio.h @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2013-2014 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LIBGPIO_H_ +#define _LIBGPIO_H_ + +#include + +__BEGIN_DECLS + +#define GPIO_INVALID_HANDLE -1 +typedef int gpio_handle_t; +typedef uint32_t gpio_pin_t; + +/* + * Structure describing a GPIO pin configuration. + */ +typedef struct { + gpio_pin_t g_pin; + char g_name[GPIOMAXNAME]; + uint32_t g_caps; + uint32_t g_flags; +} gpio_config_t; + +typedef enum { + GPIO_VALUE_INVALID = -1, + GPIO_VALUE_LOW = GPIO_PIN_LOW, + GPIO_VALUE_HIGH = GPIO_PIN_HIGH +} gpio_value_t; + +/* + * Open /dev/gpiocN or a specific device. + */ +gpio_handle_t gpio_open(unsigned int); +gpio_handle_t gpio_open_device(const char *); +void gpio_close(gpio_handle_t); +/* + * Get a list of all the GPIO pins. + */ +int gpio_pin_list(gpio_handle_t, gpio_config_t **); +/* + * GPIO pin configuration. + * + * Retrieve the configuration of a specific GPIO pin. The pin number is + * passed through the gpio_config_t structure. + */ +int gpio_pin_config(gpio_handle_t, gpio_config_t *); +/* + * Sets the GPIO flags on a specific GPIO pin. The pin number and the flags + * to be set are passed through the gpio_config_t structure. + */ +int gpio_pin_set_flags(gpio_handle_t, gpio_config_t *); +/* + * GPIO pin values. + */ +int gpio_pin_get(gpio_handle_t, gpio_pin_t); +int gpio_pin_set(gpio_handle_t, gpio_pin_t, int); +int gpio_pin_toggle(gpio_handle_t, gpio_pin_t); +/* + * Helper functions to set pin states. + */ +int gpio_pin_low(gpio_handle_t, gpio_pin_t); +int gpio_pin_high(gpio_handle_t, gpio_pin_t); +/* + * Helper functions to configure pins. + */ +int gpio_pin_input(gpio_handle_t, gpio_pin_t); +int gpio_pin_output(gpio_handle_t, gpio_pin_t); +int gpio_pin_opendrain(gpio_handle_t, gpio_pin_t); +int gpio_pin_pushpull(gpio_handle_t, gpio_pin_t); +int gpio_pin_tristate(gpio_handle_t, gpio_pin_t); +int gpio_pin_pullup(gpio_handle_t, gpio_pin_t); +int gpio_pin_pulldown(gpio_handle_t, gpio_pin_t); +int gpio_pin_invin(gpio_handle_t, gpio_pin_t); +int gpio_pin_invout(gpio_handle_t, gpio_pin_t); +int gpio_pin_pulsate(gpio_handle_t, gpio_pin_t); + +__END_DECLS + +#endif /* _LIBGPIO_H_ */ diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c index 207b9f2936a3..0edfb3f33ac1 100644 --- a/lib/libjail/jail.c +++ b/lib/libjail/jail.c @@ -531,7 +531,7 @@ jailparam_set(struct jailparam *jp, unsigned njp, int flags) } i++; } - *(const void **)&jiov[i].iov_base = "errmsg"; + jiov[i].iov_base = __DECONST(char *, "errmsg"); jiov[i].iov_len = sizeof("errmsg"); i++; jiov[i].iov_base = jail_errmsg; @@ -601,7 +601,7 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) jiov[ki].iov_len = (jp_key->jp_ctltype & CTLTYPE) == CTLTYPE_STRING ? strlen(jp_key->jp_value) + 1 : jp_key->jp_valuelen; ki++; - *(const void **)&jiov[ki].iov_base = "errmsg"; + jiov[ki].iov_base = __DECONST(char *, "errmsg"); jiov[ki].iov_len = sizeof("errmsg"); ki++; jiov[ki].iov_base = jail_errmsg; diff --git a/lib/libjail/jail_getid.c b/lib/libjail/jail_getid.c index fa1042407e69..dab2dcf25ce8 100644 --- a/lib/libjail/jail_getid.c +++ b/lib/libjail/jail_getid.c @@ -53,12 +53,12 @@ jail_getid(const char *name) jid = strtoul(name, &ep, 10); if (*name && !*ep) return jid; - *(const void **)&jiov[0].iov_base = "name"; + jiov[0].iov_base = __DECONST(char *, "name"); jiov[0].iov_len = sizeof("name"); jiov[1].iov_len = strlen(name) + 1; jiov[1].iov_base = alloca(jiov[1].iov_len); strcpy(jiov[1].iov_base, name); - *(const void **)&jiov[2].iov_base = "errmsg"; + jiov[2].iov_base = __DECONST(char *, "errmsg"); jiov[2].iov_len = sizeof("errmsg"); jiov[3].iov_base = jail_errmsg; jiov[3].iov_len = JAIL_ERRMSGLEN; @@ -80,15 +80,15 @@ jail_getname(int jid) char *name; char namebuf[MAXHOSTNAMELEN]; - *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_base = __DECONST(char *, "jid"); jiov[0].iov_len = sizeof("jid"); jiov[1].iov_base = &jid; jiov[1].iov_len = sizeof(jid); - *(const void **)&jiov[2].iov_base = "name"; + jiov[2].iov_base = __DECONST(char *, "name"); jiov[2].iov_len = sizeof("name"); jiov[3].iov_base = namebuf; jiov[3].iov_len = sizeof(namebuf); - *(const void **)&jiov[4].iov_base = "errmsg"; + jiov[4].iov_base = __DECONST(char *, "errmsg"); jiov[4].iov_len = sizeof("errmsg"); jiov[5].iov_base = jail_errmsg; jiov[5].iov_len = JAIL_ERRMSGLEN; diff --git a/lib/libkiconv/quirks.c b/lib/libkiconv/quirks.c index 2bab7c5ff0ba..d1cc607562fc 100644 --- a/lib/libkiconv/quirks.c +++ b/lib/libkiconv/quirks.c @@ -31,7 +31,7 @@ * when statically linked. */ -#ifdef __PIC__ +#ifdef PIC /* * Why do we need quirks? @@ -193,4 +193,4 @@ kiconv_quirkcs(const char* base __unused, int vendor __unused) return (base); } -#endif /* __PIC__ */ +#endif /* PIC */ diff --git a/lib/libkiconv/xlat16_iconv.c b/lib/libkiconv/xlat16_iconv.c index 702eba8e3d33..fee3c77a73af 100644 --- a/lib/libkiconv/xlat16_iconv.c +++ b/lib/libkiconv/xlat16_iconv.c @@ -31,7 +31,7 @@ * when statically linked. */ -#ifdef __PIC__ +#ifdef PIC #include #include @@ -462,4 +462,4 @@ kiconv_add_xlat16_cspairs(const char *tocode __unused, const char *fromcode __un return (-1); } -#endif /* __PIC__ */ +#endif /* PIC */ diff --git a/lib/libkiconv/xlat16_sysctl.c b/lib/libkiconv/xlat16_sysctl.c index 7c3504fb85ee..ae4dae7a5158 100644 --- a/lib/libkiconv/xlat16_sysctl.c +++ b/lib/libkiconv/xlat16_sysctl.c @@ -37,7 +37,7 @@ * when statically linked. */ -#ifdef __PIC__ +#ifdef PIC #include #include @@ -82,4 +82,4 @@ kiconv_add_xlat16_table(const char *to __unused, const char *from __unused, return (EINVAL); } -#endif /* __PIC__ */ +#endif /* PIC */ diff --git a/lib/libldns/Makefile b/lib/libldns/Makefile index db4b989506fb..9a436cdb4b9d 100644 --- a/lib/libldns/Makefile +++ b/lib/libldns/Makefile @@ -18,8 +18,7 @@ SRCS= buffer.c dane.c dname.c dnssec.c dnssec_sign.c dnssec_verify.c \ SRCS+= b64_ntop.c b64_pton.c -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD= crypto WARNS ?= 3 diff --git a/lib/libmagic/Makefile b/lib/libmagic/Makefile index 14f17028e07d..2add1d3c27b5 100644 --- a/lib/libmagic/Makefile +++ b/lib/libmagic/Makefile @@ -7,8 +7,7 @@ CONTRDIR= ${.CURDIR}/../../contrib/file LIB= magic SHLIB_MAJOR= 4 -DPADD= ${LIBZ} -LDADD= -lz +LIBADD= z MAN= libmagic.3 magic.5 SRCS= apprentice.c apptype.c ascmagic.c cdf.c cdf_time.c compress.c \ diff --git a/lib/libmd/rmd160c.c b/lib/libmd/rmd160c.c index 522b4c73d14f..e01f1e048a77 100644 --- a/lib/libmd/rmd160c.c +++ b/lib/libmd/rmd160c.c @@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$"); * The assembly-language code is not position-independent, so don't * try to use it in a shared library. */ -#ifdef __PIC__ +#ifdef PIC #undef RMD160_ASM #endif diff --git a/lib/libmd/sha1c.c b/lib/libmd/sha1c.c index 2ca4618e2453..ba3278abfff4 100644 --- a/lib/libmd/sha1c.c +++ b/lib/libmd/sha1c.c @@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$"); * The assembly-language code is not position-independent, so don't * try to use it in a shared library. */ -#ifdef __PIC__ +#ifdef PIC #undef SHA1_ASM #endif diff --git a/lib/libmemstat/Makefile b/lib/libmemstat/Makefile index d26108566a0d..597dc6db1606 100644 --- a/lib/libmemstat/Makefile +++ b/lib/libmemstat/Makefile @@ -3,8 +3,7 @@ WARNS?= 3 LIB= memstat SHLIB_MAJOR= 3 -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD+= kvm SRCS+= memstat.c SRCS+= memstat_all.c SRCS+= memstat_malloc.c diff --git a/lib/libmp/Makefile b/lib/libmp/Makefile index 5d0e7a702c55..6a73658103e5 100644 --- a/lib/libmp/Makefile +++ b/lib/libmp/Makefile @@ -4,8 +4,7 @@ LIB= mp SHLIB_MAJOR= 7 -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +LIBADD= crypto MAN= libmp.3 INCS= mp.h SRCS= mpasbn.c diff --git a/lib/libmp/tests/Makefile b/lib/libmp/tests/Makefile index 0f591eb3ea42..e74e80640e20 100644 --- a/lib/libmp/tests/Makefile +++ b/lib/libmp/tests/Makefile @@ -4,7 +4,6 @@ TESTSDIR= ${TESTSBASE}/lib/libmp TAP_TESTS_C+= legacy_test -DPADD+= ${LIBCRYPTO} ${LIBMP} -LDADD+= -lcrypto -lmp +LIBADD+= mp .include diff --git a/lib/libnv/tests/Makefile b/lib/libnv/tests/Makefile index df1054960cd2..6fe0c773c4e5 100644 --- a/lib/libnv/tests/Makefile +++ b/lib/libnv/tests/Makefile @@ -9,8 +9,7 @@ TAP_TESTS_C+= nvlist_get_test TAP_TESTS_C+= nvlist_move_test TAP_TESTS_C+= nvlist_send_recv_test -DPADD+= ${LIBNV} -LDADD+= -lnv +LIBADD+= nv WARNS?= 6 diff --git a/lib/libopie/Makefile b/lib/libopie/Makefile index e47e16d189ab..e66e67a4f9e8 100644 --- a/lib/libopie/Makefile +++ b/lib/libopie/Makefile @@ -27,8 +27,7 @@ CFLAGS+= -DINSECURE_OVERRIDE -DPATH_ACCESS_FILE=${ACCESSFILE} WARNS?= 0 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md MAN= ${OPIE_DIST}/opie.4 ${OPIE_DIST}/opiekeys.5 ${OPIE_DIST}/opieaccess.5 diff --git a/lib/libpam/libpam/tests/Makefile b/lib/libpam/libpam/tests/Makefile index 2ad64e2896d3..4532aceee393 100644 --- a/lib/libpam/libpam/tests/Makefile +++ b/lib/libpam/libpam/tests/Makefile @@ -13,7 +13,6 @@ SRCS.${test} = ${test}.c ${COMMONSRC} CFLAGS +=-I${OPENPAM}/include -I${OPENPAM}/lib/libpam -I${OPENPAM}/t WARNS ?= 6 -DPADD = ${LIBPAM} -LDADD = ${MINUSLPAM} +LIBADD = pam .include diff --git a/lib/libpam/modules/Makefile.inc b/lib/libpam/modules/Makefile.inc index 085ab58475d2..2da5a7b524ad 100644 --- a/lib/libpam/modules/Makefile.inc +++ b/lib/libpam/modules/Makefile.inc @@ -14,8 +14,7 @@ CFLAGS+= -I${PAMDIR}/include -I${.CURDIR}/../../libpam NO_PIC= .else SHLIB_NAME?= ${LIB}.so.${SHLIB_MAJOR} -DPADD+= ${LIBPAM} -LDADD+= -lpam +LIBADD+= pam .endif .include "../Makefile.inc" diff --git a/lib/libpam/modules/pam_krb5/Makefile b/lib/libpam/modules/pam_krb5/Makefile index 85f3421a1ee8..97fd49092298 100644 --- a/lib/libpam/modules/pam_krb5/Makefile +++ b/lib/libpam/modules/pam_krb5/Makefile @@ -32,7 +32,6 @@ CFLAGS+=-D_FREEFALL_CONFIG WARNS?= 3 .endif -DPADD= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR} ${LIBCRYPT} ${LIBCRYPTO} -LDADD= -lkrb5 -lhx509 -lasn1 -lroken -lcom_err -lcrypt -lcrypto +LIBADD+= krb5 .include diff --git a/lib/libpam/modules/pam_ksu/Makefile b/lib/libpam/modules/pam_ksu/Makefile index 9aa6a7e57791..26f3f850daaa 100644 --- a/lib/libpam/modules/pam_ksu/Makefile +++ b/lib/libpam/modules/pam_ksu/Makefile @@ -28,7 +28,6 @@ LIB= pam_ksu SRCS= pam_ksu.c MAN= pam_ksu.8 -DPADD= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR} ${LIBCRYPT} ${LIBCRYPTO} -LDADD= -lkrb5 -lhx509 -lasn1 -lroken -lcom_err -lcrypt -lcrypto +LIBADD+= krb5 .include diff --git a/lib/libpam/modules/pam_nologin/Makefile b/lib/libpam/modules/pam_nologin/Makefile index ba5a7d4aa770..746e9e8882ee 100644 --- a/lib/libpam/modules/pam_nologin/Makefile +++ b/lib/libpam/modules/pam_nologin/Makefile @@ -28,7 +28,6 @@ LIB= pam_nologin SRCS= pam_nologin.c MAN= pam_nologin.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD+= util .include diff --git a/lib/libpam/modules/pam_opie/Makefile b/lib/libpam/modules/pam_opie/Makefile index fbc12788e9ca..c2074bf3cbf3 100644 --- a/lib/libpam/modules/pam_opie/Makefile +++ b/lib/libpam/modules/pam_opie/Makefile @@ -29,7 +29,6 @@ LIB= pam_opie SRCS= pam_opie.c MAN= pam_opie.8 -DPADD= ${LIBOPIE} -LDADD= -lopie +LIBADD+= opie .include diff --git a/lib/libpam/modules/pam_opieaccess/Makefile b/lib/libpam/modules/pam_opieaccess/Makefile index 1554a882ba30..2e764cd43a5b 100644 --- a/lib/libpam/modules/pam_opieaccess/Makefile +++ b/lib/libpam/modules/pam_opieaccess/Makefile @@ -4,7 +4,6 @@ LIB= pam_opieaccess SRCS= ${LIB}.c MAN= pam_opieaccess.8 -DPADD= ${LIBOPIE} -LDADD= -lopie +LIBADD+= opie .include diff --git a/lib/libpam/modules/pam_passwdqc/Makefile b/lib/libpam/modules/pam_passwdqc/Makefile index c9cc30e52342..cd2364289883 100644 --- a/lib/libpam/modules/pam_passwdqc/Makefile +++ b/lib/libpam/modules/pam_passwdqc/Makefile @@ -10,8 +10,7 @@ MAN= pam_passwdqc.8 WARNS?= 2 CFLAGS+= -I${SRCDIR} -DPADD= ${LIBCRYPT} -LDADD= -lcrypt +LIBADD+= crypt .include diff --git a/lib/libpam/modules/pam_radius/Makefile b/lib/libpam/modules/pam_radius/Makefile index 2fac8334e20e..a9a93e2ab2b5 100644 --- a/lib/libpam/modules/pam_radius/Makefile +++ b/lib/libpam/modules/pam_radius/Makefile @@ -29,7 +29,6 @@ SRCS= pam_radius.c MAN= pam_radius.8 WARNS?= 3 -DPADD= ${LIBRADIUS} -LDADD= -lradius +LIBADD+= radius .include diff --git a/lib/libpam/modules/pam_ssh/Makefile b/lib/libpam/modules/pam_ssh/Makefile index 5643f321345d..b5ca478561dc 100644 --- a/lib/libpam/modules/pam_ssh/Makefile +++ b/lib/libpam/modules/pam_ssh/Makefile @@ -13,9 +13,7 @@ SRCS+= roaming_dummy.c WARNS?= 3 CFLAGS+= -I${SSHDIR} -include ssh_namespace.h -DPADD= ${LIBSSH} ${LIBCRYPTO} ${LIBCRYPT} -LDADD= ${LDSSH} -lcrypto -lcrypt -USEPRIVATELIB= ssh +LIBADD= ssh .include diff --git a/lib/libpam/modules/pam_tacplus/Makefile b/lib/libpam/modules/pam_tacplus/Makefile index 053812ac5178..5d2a3f34a4d0 100644 --- a/lib/libpam/modules/pam_tacplus/Makefile +++ b/lib/libpam/modules/pam_tacplus/Makefile @@ -28,7 +28,6 @@ LIB= pam_tacplus SRCS= pam_tacplus.c MAN= pam_tacplus.8 -DPADD= ${LIBTACPLUS} -LDADD= -ltacplus +LIBADD+= tacplus .include diff --git a/lib/libpam/modules/pam_unix/Makefile b/lib/libpam/modules/pam_unix/Makefile index ea9e639c3b5f..5330ae4a5f98 100644 --- a/lib/libpam/modules/pam_unix/Makefile +++ b/lib/libpam/modules/pam_unix/Makefile @@ -41,13 +41,11 @@ LIB= pam_unix SRCS= pam_unix.c MAN= pam_unix.8 -DPADD+= ${LIBUTIL} ${LIBCRYPT} -LDADD+= -lutil -lcrypt +LIBADD+= util crypt .if ${MK_NIS} != "no" CFLAGS+= -DYP -DPADD+= ${LIBYPCLNT} -LDADD+= -lypclnt +LIBADD+= ypclnt .endif .include diff --git a/lib/libpjdlog/Makefile b/lib/libpjdlog/Makefile index a80b6298eda5..e44f53b489fa 100644 --- a/lib/libpjdlog/Makefile +++ b/lib/libpjdlog/Makefile @@ -13,8 +13,7 @@ SHLIB_MAJOR= 0 CFLAGS+=-I${.CURDIR} -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 6 diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile index 8a0f4b2a702c..96465702c991 100644 --- a/lib/libproc/Makefile +++ b/lib/libproc/Makefile @@ -18,16 +18,13 @@ CFLAGS+= -I${.CURDIR} .if ${MK_CXX} == "no" CFLAGS+= -DNO_CXA_DEMANGLE .elif ${MK_LIBCPLUSPLUS} != "no" -LDADD+= -lcxxrt -DPADD+= ${LIBCXXRT} +LIBADD+= cxxrt .else -LDADD+= -lsupc++ -DPADD+= ${LIBSTDCPLUSPLUS} +LIBADD+= supcplusplus .endif .if ${MK_CDDL} != "no" -LDADD+= -lctf -DPADD+= ${LIBCTF} +LIBADD+= ctf IGNORE_PRAGMA= YES CFLAGS+= -I${.CURDIR}/../../cddl/contrib/opensolaris/lib/libctf/common \ -I${.CURDIR}/../../sys/cddl/contrib/opensolaris/uts/common \ diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile index 32c7daa0b19c..ff9146b4ef38 100644 --- a/lib/libprocstat/Makefile +++ b/lib/libprocstat/Makefile @@ -19,8 +19,7 @@ INCS= libprocstat.h CFLAGS+= -I. -I${.CURDIR} -D_KVM_VNODE SHLIB_MAJOR= 1 -DPADD= ${LIBELF} ${LIBKVM} ${LIBUTIL} -LDADD= -lelf -lkvm -lutil +LIBADD= elf kvm util MAN= libprocstat.3 diff --git a/lib/libradius/Makefile b/lib/libradius/Makefile index 2b769d9ee61d..42f5def20ef1 100644 --- a/lib/libradius/Makefile +++ b/lib/libradius/Makefile @@ -70,13 +70,11 @@ MLINKS+=libradius.3 rad_acct_open.3 \ WARNS?= 3 -.if ${MK_OPENSSL} == "no" -DPADD= ${LIBMD} -LDADD= -lmd -.else -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +.if ${MK_OPENSSL} != "no" +LIBADD+= crypto CFLAGS+= -DWITH_SSL +.else +LIBADD+= md .endif .include diff --git a/lib/librpcsec_gss/Makefile b/lib/librpcsec_gss/Makefile index 67a79635cc0d..c3e768445004 100644 --- a/lib/librpcsec_gss/Makefile +++ b/lib/librpcsec_gss/Makefile @@ -5,8 +5,7 @@ SHLIB_MAJOR= 1 SRCS+= rpcsec_gss.c rpcsec_gss_prot.c rpcsec_gss_conf.c rpcsec_gss_misc.c \ svc_rpcsec_gss.c -DPADD+= ${LIBGSSAPI} -LDADD+= -lgssapi +LIBADD= gssapi VERSION_DEF= ${.CURDIR}/../libc/Versions.def SYMBOL_MAPS= ${.CURDIR}/Symbol.map diff --git a/lib/librt/Makefile b/lib/librt/Makefile index bd6ec0717d91..36296101a6f7 100644 --- a/lib/librt/Makefile +++ b/lib/librt/Makefile @@ -9,8 +9,7 @@ CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR} CFLAGS+=-fexceptions .endif CFLAGS+=-Winline -Wall -DPADD= ${LIBPTHREAD} -LDADD= -lpthread +LIBADD= pthread WARNS?= 2 diff --git a/lib/librt/tests/Makefile b/lib/librt/tests/Makefile index 224f52ea85aa..95c525997e3b 100644 --- a/lib/librt/tests/Makefile +++ b/lib/librt/tests/Makefile @@ -6,8 +6,7 @@ TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/librt TESTSDIR= ${TESTSBASE}/lib/librt -DPADD+= ${LIBRT} -LDADD+= -lrt +LIBADD= rt NETBSD_ATF_TESTS_C= sched_test NETBSD_ATF_TESTS_C+= sem_test diff --git a/lib/libsmb/Makefile b/lib/libsmb/Makefile index ea7327b3e94c..b63754bd982a 100644 --- a/lib/libsmb/Makefile +++ b/lib/libsmb/Makefile @@ -7,8 +7,7 @@ CONTRIBDIR= ${.CURDIR}/../../contrib/smbfs LIB= smb SHLIB_MAJOR= 4 -DPADD= ${LIBKICONV} -LDADD= -lkiconv +LIBADD= kiconv SRCS= rcfile.c ctx.c cfopt.c subr.c nls.c rap.c mbuf.c rq.c file.c \ print.c \ diff --git a/lib/libsqlite3/Makefile b/lib/libsqlite3/Makefile index 78ee86d1ab83..2db85fb39708 100644 --- a/lib/libsqlite3/Makefile +++ b/lib/libsqlite3/Makefile @@ -3,6 +3,7 @@ PRIVATELIB= yes LIB= sqlite3 SHLIB_MAJOR?= 0 +LIBADD+= pthread SRCS= sqlite3.c diff --git a/lib/libstdthreads/Makefile b/lib/libstdthreads/Makefile index 544eeb0f12f1..8daee58b0e87 100644 --- a/lib/libstdthreads/Makefile +++ b/lib/libstdthreads/Makefile @@ -32,8 +32,7 @@ MLINKS= thrd_create.3 call_once.3 \ thrd_create.3 tss_get.3 \ thrd_create.3 tss_set.3 -DPADD= ${LIBPTHREAD} -LDADD= -lpthread +LIBADD= pthread VERSION_DEF= ${.CURDIR}/../libc/Versions.def SYMBOL_MAPS= ${.CURDIR}/Symbol.map diff --git a/lib/libtacplus/Makefile b/lib/libtacplus/Makefile index 798c94978a78..01345e175a6b 100644 --- a/lib/libtacplus/Makefile +++ b/lib/libtacplus/Makefile @@ -28,8 +28,7 @@ LIB= tacplus SRCS= taclib.c INCS= taclib.h CFLAGS+= -Wall -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md SHLIB_MAJOR= 5 MAN= libtacplus.3 tacplus.conf.5 diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c index 7b13db667be7..7001311e6d89 100644 --- a/lib/libthr/thread/thr_exit.c +++ b/lib/libthr/thread/thr_exit.c @@ -54,7 +54,7 @@ __weak_reference(_pthread_exit, pthread_exit); static int message_printed; static void thread_unwind(void) __dead2; -#ifdef __PIC__ +#ifdef PIC static void thread_uw_init(void); static _Unwind_Reason_Code thread_unwind_stop(int version, _Unwind_Action actions, @@ -114,7 +114,7 @@ _Unwind_GetCFA(struct _Unwind_Context *context) #else #pragma weak _Unwind_GetCFA #pragma weak _Unwind_ForcedUnwind -#endif /* __PIC__ */ +#endif /* PIC */ static void thread_unwind_cleanup(_Unwind_Reason_Code code, struct _Unwind_Exception *e) @@ -222,11 +222,11 @@ _pthread_exit_mask(void *status, sigset_t *mask) curthread->ret = status; #ifdef _PTHREAD_FORCED_UNWIND -#ifdef __PIC__ +#ifdef PIC thread_uw_init(); -#endif /* __PIC__ */ +#endif /* PIC */ -#ifdef __PIC__ +#ifdef PIC if (uwl_forcedunwind != NULL) { #else if (_Unwind_ForcedUnwind != NULL) { diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index f9735e7cbcad..c6651cd2dc7e 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -100,7 +100,7 @@ TAILQ_HEAD(mutex_queue, pthread_mutex); #define THR_ASSERT(cond, msg) #endif -#ifdef __PIC__ +#ifdef PIC # define STATIC_LIB_REQUIRE(name) #else # define STATIC_LIB_REQUIRE(name) __asm (".globl " #name) diff --git a/lib/libucl/Makefile b/lib/libucl/Makefile index 830c198bb490..31bd3166f045 100644 --- a/lib/libucl/Makefile +++ b/lib/libucl/Makefile @@ -16,6 +16,8 @@ SRCS= ucl_emitter_streamline.c \ .PATH: ${LIBUCL}/src +LIBADD= m + WARNS= 1 CFLAGS+= -I${LIBUCL}/include \ -I${LIBUCL}/src \ diff --git a/lib/libulog/Makefile b/lib/libulog/Makefile index efbaece8fefb..fedd114efb9e 100644 --- a/lib/libulog/Makefile +++ b/lib/libulog/Makefile @@ -19,8 +19,7 @@ MLINKS+=ulog_login.3 ulog_login_pseudo.3 \ utempter_remove_added_record.3 removeFromUtmp.3 \ utempter_remove_record.3 removeLineFromUtmp.3 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md VERSION_DEF= ${.CURDIR}/../libc/Versions.def SYMBOL_MAPS= ${.CURDIR}/Symbol.map diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile index aca30237ad1e..e05d214a22b7 100644 --- a/lib/libunbound/Makefile +++ b/lib/libunbound/Makefile @@ -28,8 +28,7 @@ SRCS= alloc.c autotrust.c config_file.c configlexer.l configparser.y \ WARNS?= 3 -DPADD+= ${LIBSSL} ${LIBCRYPTO} ${LIBPTHREAD} -LDADD+= -lssl -lcrypto -lpthread +LIBADD= ssl crypto pthread # Misnamed file in upstream source configlexer.l: configlexer.lex diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile index 1ef85d4b6f50..24d97fd63aac 100644 --- a/lib/libusb/Makefile +++ b/lib/libusb/Makefile @@ -19,8 +19,7 @@ PTHREAD_LIBS?= -lpthread WARNS?= 2 -DPADD= ${LIBPTHREAD} -LDADD= ${PTHREAD_LIBS} +LIBADD= pthread MLINKS+= libusb.3 usb.3 diff --git a/lib/libutil/tests/Makefile b/lib/libutil/tests/Makefile index 31b6c54063c6..36eb2ae55d37 100644 --- a/lib/libutil/tests/Makefile +++ b/lib/libutil/tests/Makefile @@ -9,7 +9,6 @@ TAP_TESTS_C+= pidfile_test TAP_TESTS_C+= trimdomain_test TAP_TESTS_C+= trimdomain-nodomain_test -DPADD+= ${LIBUTIL} -LDADD+= -lutil +LIBADD+= util .include diff --git a/lib/msun/src/s_isnan.c b/lib/msun/src/s_isnan.c index eabae9db9fc7..a54ded3fe44c 100644 --- a/lib/msun/src/s_isnan.c +++ b/lib/msun/src/s_isnan.c @@ -31,7 +31,7 @@ #include "fpmath.h" /* Provided by libc.so */ -#ifndef __PIC__ +#ifndef PIC #undef isnan int isnan(double d) @@ -41,7 +41,7 @@ isnan(double d) u.d = d; return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); } -#endif /* !__PIC__ */ +#endif /* !PIC */ int __isnanf(float f) diff --git a/lib/msun/tests/Makefile b/lib/msun/tests/Makefile index 4261e4865b52..cb06868958ab 100644 --- a/lib/msun/tests/Makefile +++ b/lib/msun/tests/Makefile @@ -41,8 +41,7 @@ NETBSD_ATF_TESTS_C+= tanh_test CSTD= c99 -LDADD+= -lm -DPADD+= ${LIBM} +LIBADD+= m #COPTS+= -Wfloat-equal # Copied from lib/msun/Makefile diff --git a/lib/ncurses/form/Makefile b/lib/ncurses/form/Makefile index dd903b05c626..beefb2c4a7d2 100644 --- a/lib/ncurses/form/Makefile +++ b/lib/ncurses/form/Makefile @@ -54,8 +54,7 @@ CLEANFILES= ncurses_def.h CFLAGS+= -I${SRCDIR} CFLAGS+= -I${NCURSES_DIR}/menu -DPADD= ${LIBNCURSES${LIB_SUFFIX:tu}} -LDADD= -lncurses${LIB_SUFFIX} +LIBADD+= ncurses${LIB_SUFFIX} .if defined(ENABLE_WIDEC) INCS= form.h diff --git a/lib/ncurses/menu/Makefile b/lib/ncurses/menu/Makefile index 3aac08170623..d3890de73e36 100644 --- a/lib/ncurses/menu/Makefile +++ b/lib/ncurses/menu/Makefile @@ -40,8 +40,7 @@ CLEANFILES= ncurses_def.h CFLAGS+= -I${SRCDIR} -DPADD= ${LIBNCURSES${LIB_SUFFIX:tu}} -LDADD= -lncurses${LIB_SUFFIX} +LIBADD+= ncurses${LIB_SUFFIX} .if defined(ENABLE_WIDEC) INCS= menu.h eti.h diff --git a/lib/ncurses/panel/Makefile b/lib/ncurses/panel/Makefile index 7929aed4d025..b075bcf056af 100644 --- a/lib/ncurses/panel/Makefile +++ b/lib/ncurses/panel/Makefile @@ -29,8 +29,7 @@ CLEANFILES= ncurses_def.h CFLAGS+= -I${SRCDIR} -DPADD= ${LIBNCURSES${LIB_SUFFIX:tu}} -LDADD= -lncurses${LIB_SUFFIX} +LIBADD+= ncurses${LIB_SUFFIX} .if defined(ENABLE_WIDEC) INCS= panel.h diff --git a/libexec/atf/atf-check/Makefile b/libexec/atf/atf-check/Makefile index 2a9851eeea5a..5bef488fc1b1 100644 --- a/libexec/atf/atf-check/Makefile +++ b/libexec/atf/atf-check/Makefile @@ -38,9 +38,7 @@ MAN= atf-check.1 CFLAGS+= -I${ATF} CFLAGS+= -DATF_SHELL='"/bin/sh"' -DPADD+= ${LIBATF_CXX} ${LIBATF_C} -LDADD+= ${LDATF_CXX} ${LDATF_C} -USEPRIVATELIB= atf-c++ atf-c +LIBADD= atf_cxx .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/libexec/atf/atf-sh/Makefile b/libexec/atf/atf-sh/Makefile index 4e14643c0574..f00683fa1e58 100644 --- a/libexec/atf/atf-sh/Makefile +++ b/libexec/atf/atf-sh/Makefile @@ -42,9 +42,7 @@ CFLAGS+= -DATF_PKGDATADIR='"${SHAREDIR}/atf"' CFLAGS+= -DATF_SHELL='"/bin/sh"' CFLAGS+= -I${ATF} -DPADD+= ${LIBATF_C} ${LIBATF_CXX} -LDADD+= ${LDATF_C} ${LDATF_CXX} -USEPRIVATELIB= atf-c++ atf-c +LIBADD= atf_cxx FILESGROUPS= SUBR diff --git a/libexec/atrun/Makefile b/libexec/atrun/Makefile index 273055997c0b..39952fc430ea 100644 --- a/libexec/atrun/Makefile +++ b/libexec/atrun/Makefile @@ -17,8 +17,7 @@ CFLAGS+=-DLOGIN_CAP -DPAM WARNS?= 2 WFORMAT=0 -DPADD= ${LIBPAM} ${LIBUTIL} -LDADD= ${MINUSLPAM} -lutil +LIBADD= pam util atrun.8: atrun.man @${ECHO} Making ${.TARGET:T} from ${.ALLSRC:T}; \ diff --git a/libexec/casper/dns/Makefile b/libexec/casper/dns/Makefile index 245493e9c6f0..b101891cc954 100644 --- a/libexec/casper/dns/Makefile +++ b/libexec/casper/dns/Makefile @@ -6,8 +6,7 @@ PROG= dns SRCS= dns.c -DPADD= ${LIBCAPSICUM} ${LIBCASPER} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcapsicum -lcasper -lnv -lpjdlog -lutil +LIBADD= casper nv BINDIR= /libexec/casper diff --git a/libexec/casper/grp/Makefile b/libexec/casper/grp/Makefile index 502cd261f595..75274d101a2c 100644 --- a/libexec/casper/grp/Makefile +++ b/libexec/casper/grp/Makefile @@ -6,8 +6,7 @@ PROG= grp SRCS= grp.c -DPADD= ${LIBCAPSICUM} ${LIBCASPER} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcapsicum -lcasper -lnv -lpjdlog -lutil +LIBADD= casper nv pjdlog BINDIR= /libexec/casper diff --git a/libexec/casper/pwd/Makefile b/libexec/casper/pwd/Makefile index ebf6cac9e121..23ad3f277a81 100644 --- a/libexec/casper/pwd/Makefile +++ b/libexec/casper/pwd/Makefile @@ -6,8 +6,7 @@ PROG= pwd SRCS= pwd.c -DPADD= ${LIBCAPSICUM} ${LIBCASPER} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcapsicum -lcasper -lnv -lpjdlog -lutil +LIBADD= casper nv pjdlog BINDIR= /libexec/casper diff --git a/libexec/casper/random/Makefile b/libexec/casper/random/Makefile index 46c97393335b..3b5d15585afd 100644 --- a/libexec/casper/random/Makefile +++ b/libexec/casper/random/Makefile @@ -6,8 +6,7 @@ PROG= random SRCS= random.c -DPADD= ${LIBCAPSICUM} ${LIBCASPER} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcapsicum -lcasper -lnv -lpjdlog -lutil +LIBADD= casper nv BINDIR= /libexec/casper diff --git a/libexec/casper/sysctl/Makefile b/libexec/casper/sysctl/Makefile index 432008e01e75..24152abdc90e 100644 --- a/libexec/casper/sysctl/Makefile +++ b/libexec/casper/sysctl/Makefile @@ -6,8 +6,7 @@ PROG= sysctl SRCS= sysctl.c -DPADD= ${LIBCAPSICUM} ${LIBCASPER} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcapsicum -lcasper -lnv -lpjdlog -lutil +LIBADD= casper nv pjdlog BINDIR= /libexec/casper diff --git a/libexec/dma/Makefile b/libexec/dma/Makefile index 757faf4a3c34..65c738202842 100644 --- a/libexec/dma/Makefile +++ b/libexec/dma/Makefile @@ -8,8 +8,7 @@ CFLAGS= -I${.CURDIR}/../../contrib/dma \ -DLIBEXEC_PATH='"/usr/libexec"' -DDMA_VERSION='"v0.9+"' \ -DDMA_ROOT_USER='"mailnull"' \ -DDMA_GROUP='"mail"' -DPADD= ${LIBSSL} ${LIBCRYPTO} -LDADD= -lssl -lcrypto +LIBADD= ssl crypto PROG= dma SRCS= aliases_parse.y \ diff --git a/libexec/fingerd/Makefile b/libexec/fingerd/Makefile index b6382ad79706..f7101735b7e8 100644 --- a/libexec/fingerd/Makefile +++ b/libexec/fingerd/Makefile @@ -2,8 +2,7 @@ # $FreeBSD$ PROG= fingerd -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util MAN= fingerd.8 WARNS?= 2 diff --git a/libexec/ftpd/Makefile b/libexec/ftpd/Makefile index 0c7c9826a843..da41967234b1 100644 --- a/libexec/ftpd/Makefile +++ b/libexec/ftpd/Makefile @@ -13,19 +13,16 @@ YFLAGS= WARNS?= 2 WFORMAT=0 -DPADD= ${LIBUTIL} ${LIBCRYPT} -LDADD= -lutil -lcrypt +LIBADD= util crypt # XXX Kluge! Conversation mechanism needs to be fixed. -DPADD+= ${LIBOPIE} ${LIBMD} -LDADD+= -lopie -lmd +LIBADD+= opie md LSDIR= ../../bin/ls .PATH: ${.CURDIR}/${LSDIR} SRCS+= ls.c cmp.c print.c util.c CFLAGS+=-Dmain=ls_main -I${.CURDIR}/${LSDIR} -DPADD+= ${LIBM} -LDADD+= -lm +LIBADD+= m .if ${MK_INET6_SUPPORT} != "no" CFLAGS+=-DINET6 @@ -33,8 +30,7 @@ CFLAGS+=-DINET6 .if ${MK_PAM_SUPPORT} != "no" CFLAGS+=-DUSE_PAM -DPADD+= ${LIBPAM} -LDADD+= ${MINUSLPAM} +LIBADD+= pam .endif .include diff --git a/libexec/getty/Makefile b/libexec/getty/Makefile index f9679586a487..976d62a71f2c 100644 --- a/libexec/getty/Makefile +++ b/libexec/getty/Makefile @@ -3,8 +3,7 @@ PROG= getty SRCS= main.c init.c subr.c chat.c -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util MAN= gettytab.5 ttys.5 getty.8 WARNS?= 1 diff --git a/libexec/mail.local/Makefile b/libexec/mail.local/Makefile index 3e59609e893e..018357c71c25 100644 --- a/libexec/mail.local/Makefile +++ b/libexec/mail.local/Makefile @@ -12,11 +12,7 @@ CFLAGS+=-I${SENDMAIL_DIR}/include -I. WARNS?= 2 WFORMAT=0 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -DPADD= ${LIBSM} -LDADD= ${LIBSM} +LIBADD= sm SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/libexec/pppoed/Makefile b/libexec/pppoed/Makefile index 1ffaffe3eed2..09c3ee629c24 100644 --- a/libexec/pppoed/Makefile +++ b/libexec/pppoed/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ PROG= pppoed -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph MAN= pppoed.8 WARNS?= 1 diff --git a/libexec/rlogind/Makefile b/libexec/rlogind/Makefile index de0fb20e2961..282ec6389611 100644 --- a/libexec/rlogind/Makefile +++ b/libexec/rlogind/Makefile @@ -5,8 +5,7 @@ PROG= rlogind MAN= rlogind.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 2 .if ${MK_INET6_SUPPORT} != "no" diff --git a/libexec/rpc.rquotad/Makefile b/libexec/rpc.rquotad/Makefile index 95d4415e538b..21cb45d18ad0 100644 --- a/libexec/rpc.rquotad/Makefile +++ b/libexec/rpc.rquotad/Makefile @@ -4,7 +4,6 @@ PROG = rpc.rquotad SRCS = rquotad.c MAN = rpc.rquotad.8 -DPADD= ${LIBRPCSVC} ${LIBUTIL} -LDADD= -lrpcsvc -lutil +LIBADD= rpcsvc util .include diff --git a/libexec/rpc.rstatd/Makefile b/libexec/rpc.rstatd/Makefile index a42225f9e1ca..f408d4a337bc 100644 --- a/libexec/rpc.rstatd/Makefile +++ b/libexec/rpc.rstatd/Makefile @@ -4,8 +4,7 @@ PROG = rpc.rstatd SRCS = rstatd.c rstat_proc.c MAN = rpc.rstatd.8 -DPADD= ${LIBRPCSVC} ${LIBUTIL} ${LIBDEVSTAT} ${LIBKVM} -LDADD= -lrpcsvc -lutil -ldevstat -lkvm +LIBADD= rpcsvc devstat WARNS?= 1 diff --git a/libexec/rpc.rusersd/Makefile b/libexec/rpc.rusersd/Makefile index 7801a0cdcb0c..2de7ebb52aca 100644 --- a/libexec/rpc.rusersd/Makefile +++ b/libexec/rpc.rusersd/Makefile @@ -4,7 +4,6 @@ PROG = rpc.rusersd SRCS = rusersd.c rusers_proc.c extern.h MAN = rpc.rusersd.8 -DPADD= ${LIBRPCSVC} ${LIBUTIL} -LDADD= -lrpcsvc -lutil +LIBADD= rpcsvc .include diff --git a/libexec/rpc.rwalld/Makefile b/libexec/rpc.rwalld/Makefile index b09d66358556..6606a178f7a6 100644 --- a/libexec/rpc.rwalld/Makefile +++ b/libexec/rpc.rwalld/Makefile @@ -4,8 +4,7 @@ PROG = rpc.rwalld SRCS = rwalld.c MAN = rpc.rwalld.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 2 diff --git a/libexec/rpc.sprayd/Makefile b/libexec/rpc.sprayd/Makefile index 5b1cb241c258..51ac6bf8d090 100644 --- a/libexec/rpc.sprayd/Makefile +++ b/libexec/rpc.sprayd/Makefile @@ -4,8 +4,7 @@ PROG = rpc.sprayd SRCS = sprayd.c MAN = rpc.sprayd.8 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc WARNS?= 2 diff --git a/libexec/rshd/Makefile b/libexec/rshd/Makefile index f6881e8e1c57..c856995c5248 100644 --- a/libexec/rshd/Makefile +++ b/libexec/rshd/Makefile @@ -7,7 +7,6 @@ MAN= rshd.8 WARNS?= 3 WFORMAT=0 -DPADD= ${LIBUTIL} ${LIBPAM} -LDADD= -lutil ${MINUSLPAM} +LIBADD= util pam .include diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index cc301328fb39..09dc4ab968c9 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -43,16 +43,14 @@ CFLAGS+= -fpic .endif CFLAGS+= -DPIC $(DEBUG) LDFLAGS+= -shared -Wl,-Bsymbolic -DPADD= ${LIBC_PIC} -LDADD= -lc_pic +LIBADD= c_pic .if ${MACHINE_CPUARCH} == "arm" # Some of the required math functions (div & mod) are implemented in # libcompiler_rt on ARM. The library also needs to be placed first to be # correctly linked. As some of the functions are used before we have # shared libraries. -DPADD+= ${LIBCOMPILER_RT} -LDADD+= -lcompiler_rt +LIBADD+= compiler_rt .endif diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 57cb306584b2..cc7afdad60ba 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1817,7 +1817,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) objtmp.path = NULL; objtmp.rtld = true; objtmp.mapbase = mapbase; -#ifdef __PIC__ +#ifdef PIC objtmp.relocbase = mapbase; #endif if (RTLD_IS_DYNAMIC()) { diff --git a/libexec/smrsh/Makefile b/libexec/smrsh/Makefile index ae86155d0d00..7e82b22b0a02 100644 --- a/libexec/smrsh/Makefile +++ b/libexec/smrsh/Makefile @@ -9,11 +9,7 @@ SRCS= smrsh.c MAN= smrsh.8 CFLAGS+=-I${SENDMAIL_DIR}/src -I${SENDMAIL_DIR}/include -I. -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -DPADD= ${LIBSM} -LDADD= ${LIBSM} +LIBADD= sm WARNS?= 2 diff --git a/libexec/tcpd/Makefile b/libexec/tcpd/Makefile index f3fbf29b5d5f..03e8c52069af 100644 --- a/libexec/tcpd/Makefile +++ b/libexec/tcpd/Makefile @@ -15,8 +15,7 @@ CFLAGS+=-DREAL_DAEMON_DIR=\"/usr/libexec\" \ CFLAGS+=-DINET6 .endif -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap WARNS?= 1 diff --git a/libexec/telnetd/Makefile b/libexec/telnetd/Makefile index 07de1970471e..7cb9bc972ce2 100644 --- a/libexec/telnetd/Makefile +++ b/libexec/telnetd/Makefile @@ -29,20 +29,17 @@ CFLAGS+= -I${TELNETDIR}/telnet LIBTELNET= ${.OBJDIR}/../../lib/libtelnet/libtelnet.a -DPADD= ${LIBUTIL} ${LIBTERMCAPW} ${LIBTELNET} -LDADD= -lutil -ltermcapw ${LIBTELNET} +LIBADD= telnet util ncursesw .if ${MK_OPENSSL} != "no" SRCS+= authenc.c CFLAGS+= -DAUTHENTICATION -DENCRYPTION -DPADD+= ${LIBMP} ${LIBCRYPTO} ${LIBCRYPT} ${LIBPAM} -LDADD+= -lmp -lcrypto -lcrypt ${MINUSLPAM} +LIBADD+= mp crypto pam .endif .if ${MK_KERBEROS_SUPPORT} != "no" CFLAGS+= -DKRB5 -DFORWARD -Dnet_write=telnet_net_write -DPADD+= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR} -LDADD+= -lkrb5 -lhx509 -lasn1 -lroken -lcom_err +LIBADD+= krb5 roken .endif .include diff --git a/libexec/tftpd/Makefile b/libexec/tftpd/Makefile index f005001bbb8b..015458c093fe 100644 --- a/libexec/tftpd/Makefile +++ b/libexec/tftpd/Makefile @@ -7,7 +7,6 @@ SRCS= tftp-file.c tftp-io.c tftp-options.c tftp-transfer.c tftp-utils.c SRCS+= tftpd.c WFORMAT=0 -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap .include diff --git a/libexec/ulog-helper/Makefile b/libexec/ulog-helper/Makefile index 764f0dece164..b763643fb5d9 100644 --- a/libexec/ulog-helper/Makefile +++ b/libexec/ulog-helper/Makefile @@ -5,7 +5,6 @@ BINOWN= root BINMODE=4555 MAN= -DPADD= ${LIBULOG} -LDADD= -lulog +LIBADD= ulog .include diff --git a/libexec/ypxfr/Makefile b/libexec/ypxfr/Makefile index 476a296fa7f3..d1a2f573a823 100644 --- a/libexec/ypxfr/Makefile +++ b/libexec/ypxfr/Makefile @@ -16,8 +16,7 @@ CFLAGS+= -I. WARNS?= 2 WFORMAT=0 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc CLEANFILES= ${GENSRCS} diff --git a/release/picobsd/tinyware/login/Makefile b/release/picobsd/tinyware/login/Makefile index 0a39c756ad18..bc6156c8ac51 100644 --- a/release/picobsd/tinyware/login/Makefile +++ b/release/picobsd/tinyware/login/Makefile @@ -11,13 +11,11 @@ MAN= login.1 CFLAGS+=-DLOGALL -DPADD= ${LIBUTIL} ${LIBCRYPT} -LDADD= -lutil -lcrypt +LIBADD= util crypt .if ${MK_PAM_SUPPORT} != "no" CFLAGS+= -DUSE_PAM -DPADD+= ${LIBPAM} -LDADD+= ${MINUSLPAM} +LIBADD+= pam .endif BINOWN= root diff --git a/release/picobsd/tinyware/oinit/Makefile b/release/picobsd/tinyware/oinit/Makefile index 74044afa779e..072bbba8a840 100644 --- a/release/picobsd/tinyware/oinit/Makefile +++ b/release/picobsd/tinyware/oinit/Makefile @@ -14,7 +14,7 @@ CFLAGS= -DSH_PATH=\"${SH_PATH}\" -DSH_NAME=\"${SH_NAME}\" \ #CFLAGS+= -DOINIT_RC=\"/etc/oinit.rc\" #LDADD= -lutil -ledit -ltermcap -LDADD=-lutil +LIBADD= util MAN= .include diff --git a/release/picobsd/tinyware/passwd/Makefile b/release/picobsd/tinyware/passwd/Makefile index fa603083bcce..806836c4fea3 100644 --- a/release/picobsd/tinyware/passwd/Makefile +++ b/release/picobsd/tinyware/passwd/Makefile @@ -11,8 +11,7 @@ GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c \ yppasswd_private.h yppasswd_private_clnt.c yppasswd_private_xdr.c CFLAGS+=-Wall -DPADD= ${LIBCRYPT} ${LIBUTIL} -LDADD= -lcrypt -lutil +LIBADD= crypt util .PATH: ${.CURDIR}/../../../../usr.bin/chpass \ # ${.CURDIR}/../../../../usr.sbin/vipw \ # ${.CURDIR}/../../../../usr.bin/passwd diff --git a/sbin/atm/atmconfig/Makefile b/sbin/atm/atmconfig/Makefile index f3dce2663f9a..1e48f0454d32 100644 --- a/sbin/atm/atmconfig/Makefile +++ b/sbin/atm/atmconfig/Makefile @@ -17,11 +17,9 @@ CFLAGS+= -I${.OBJDIR} .if !defined(RESCUE) && ${MK_BSNMP} != "no" CFLAGS+= -DWITH_BSNMP SRCS+= oid.h atmconfig_device.c -DPADD+= ${LIBBSNMP} -LDADD+= -lbsnmp +LIBADD+= bsnmp . if ${MK_DYNAMICROOT} == "no" && ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto . endif .endif diff --git a/sbin/badsect/Makefile b/sbin/badsect/Makefile index b6cb545e09f5..c11f8cba506a 100644 --- a/sbin/badsect/Makefile +++ b/sbin/badsect/Makefile @@ -2,8 +2,7 @@ # $FreeBSD$ PROG= badsect -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs MAN= badsect.8 WARNS?= 2 diff --git a/sbin/bsdlabel/Makefile b/sbin/bsdlabel/Makefile index e51e928afb24..42f0f1c3861a 100644 --- a/sbin/bsdlabel/Makefile +++ b/sbin/bsdlabel/Makefile @@ -12,7 +12,6 @@ LINKS= ${BINDIR}/bsdlabel ${BINDIR}/disklabel MLINKS= bsdlabel.8 disklabel.8 .endif -DPADD= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} -LDADD= -lgeom -lbsdxml -lsbuf +LIBADD= geom .include diff --git a/sbin/camcontrol/Makefile b/sbin/camcontrol/Makefile index 4f11f195db5b..f23ef521a8b7 100644 --- a/sbin/camcontrol/Makefile +++ b/sbin/camcontrol/Makefile @@ -11,8 +11,7 @@ CFLAGS+= -DMINIMALISTIC .if ${MACHINE_CPUARCH} == "arm" WARNS?= 3 .endif -DPADD= ${LIBCAM} ${LIBSBUF} ${LIBUTIL} -LDADD= -lcam -lsbuf -lutil +LIBADD= cam sbuf util MAN= camcontrol.8 .include diff --git a/sbin/casperd/Makefile b/sbin/casperd/Makefile index f5a8e05860a8..93f145ceeb38 100644 --- a/sbin/casperd/Makefile +++ b/sbin/casperd/Makefile @@ -4,8 +4,7 @@ PROG= casperd SRCS= casperd.c zygote.c -DPADD= ${LIBCASPER} ${LIBCAPSICUM} ${LIBNV} ${LIBPJDLOG} ${LIBUTIL} -LDADD= -lcasper -lcapsicum -lnv -lpjdlog -lutil +LIBADD= casper nv pjdlog util MAN= casperd.8 diff --git a/sbin/ccdconfig/Makefile b/sbin/ccdconfig/Makefile index 0feca5426dec..3b64dafb5c83 100644 --- a/sbin/ccdconfig/Makefile +++ b/sbin/ccdconfig/Makefile @@ -3,7 +3,6 @@ PROG= ccdconfig MAN= ccdconfig.8 -DPADD= ${LIBGEOM} -LDADD= -lgeom +LIBADD= geom .include diff --git a/sbin/ddb/Makefile b/sbin/ddb/Makefile index c556be12f016..72abbed337ae 100644 --- a/sbin/ddb/Makefile +++ b/sbin/ddb/Makefile @@ -5,7 +5,6 @@ SRCS= ddb.c ddb_capture.c ddb_script.c MAN= ddb.8 WARNS?= 3 -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm .include diff --git a/sbin/devd/Makefile b/sbin/devd/Makefile index 518e5e2c21d5..fc0021656beb 100644 --- a/sbin/devd/Makefile +++ b/sbin/devd/Makefile @@ -10,8 +10,7 @@ WARNS?= 3 NO_SHARED?=YES -DPADD= ${LIBL} ${LIBUTIL} -LDADD= -ll -lutil +LIBADD= l util YFLAGS+=-v CFLAGS+=-I. -I${.CURDIR} diff --git a/sbin/dhclient/Makefile b/sbin/dhclient/Makefile index 09f19db0747e..868df6d6ba65 100644 --- a/sbin/dhclient/Makefile +++ b/sbin/dhclient/Makefile @@ -41,8 +41,7 @@ PROG= dhclient SCRIPTS=dhclient-script MAN= dhclient.8 dhclient.conf.5 dhclient.leases.5 dhcp-options.5 \ dhclient-script.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 2 diff --git a/sbin/dmesg/Makefile b/sbin/dmesg/Makefile index 266551be5765..64a0155917be 100644 --- a/sbin/dmesg/Makefile +++ b/sbin/dmesg/Makefile @@ -4,7 +4,6 @@ PROG= dmesg MAN= dmesg.8 -LDADD= -lkvm -DPADD= ${LIBKVM} +LIBADD= kvm .include diff --git a/sbin/dumpfs/Makefile b/sbin/dumpfs/Makefile index fe464e03f7be..87eb89b1782e 100644 --- a/sbin/dumpfs/Makefile +++ b/sbin/dumpfs/Makefile @@ -3,8 +3,7 @@ PROG= dumpfs WARNS?= 2 -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs MAN= dumpfs.8 .include diff --git a/sbin/fdisk/Makefile b/sbin/fdisk/Makefile index 795377917e1c..a49c69954d0f 100644 --- a/sbin/fdisk/Makefile +++ b/sbin/fdisk/Makefile @@ -7,8 +7,7 @@ MAN= fdisk.8 .PATH: ${.CURDIR}/../../sys/geom -DPADD+= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} -LDADD+= -lgeom -lbsdxml -lsbuf +LIBADD= geom .include diff --git a/sbin/fdisk_pc98/Makefile b/sbin/fdisk_pc98/Makefile index 6961d31d58a8..9915267e6d7c 100644 --- a/sbin/fdisk_pc98/Makefile +++ b/sbin/fdisk_pc98/Makefile @@ -7,7 +7,6 @@ MAN= fdisk.8 .PATH: ${.CURDIR}/../../sys/geom -DPADD+= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} -LDADD+= -lgeom -lbsdxml -lsbuf +LIBADD= geom .include diff --git a/sbin/ffsinfo/Makefile b/sbin/ffsinfo/Makefile index cb4e8f945979..7fd033d3475a 100644 --- a/sbin/ffsinfo/Makefile +++ b/sbin/ffsinfo/Makefile @@ -13,7 +13,6 @@ MAN= ffsinfo.8 WARNS?= 1 CFLAGS+=-DFS_DEBUG -I${GROWFS} -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs .include diff --git a/sbin/fsck_ffs/Makefile b/sbin/fsck_ffs/Makefile index 028a4867c85d..02754697dfa5 100644 --- a/sbin/fsck_ffs/Makefile +++ b/sbin/fsck_ffs/Makefile @@ -9,8 +9,7 @@ MLINKS= fsck_ffs.8 fsck_ufs.8 fsck_ffs.8 fsck_4.2bsd.8 SRCS= dir.c ea.c fsutil.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c \ pass4.c pass5.c setup.c suj.c utilities.c gjournal.c getmntopts.c \ globs.c -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs WARNS?= 2 CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../mount diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c index 7640f704b76a..9203000f4fce 100644 --- a/sbin/fsck_ffs/dir.c +++ b/sbin/fsck_ffs/dir.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include diff --git a/sbin/fsdb/Makefile b/sbin/fsdb/Makefile index 21ac09f9c66d..e0a9cc3cb382 100644 --- a/sbin/fsdb/Makefile +++ b/sbin/fsdb/Makefile @@ -9,8 +9,7 @@ SRCS= fsdb.c fsdbutil.c \ pass5.c setup.c utilities.c ffs_subr.c ffs_tables.c globs.c CFLAGS+= -I${.CURDIR}/../fsck_ffs WARNS?= 2 -LDADD= -ledit -ltermcapw -DPADD= ${LIBEDIT} ${LIBTERMCAPW} +LIBADD= edit .PATH: ${.CURDIR}/../fsck_ffs ${.CURDIR}/../../sys/ufs/ffs .include diff --git a/sbin/gbde/Makefile b/sbin/gbde/Makefile index 019ee18f8af3..c33136b05e14 100644 --- a/sbin/gbde/Makefile +++ b/sbin/gbde/Makefile @@ -20,8 +20,7 @@ CFLAGS+= -I${.CURDIR}/../../sys CLEANFILES+= template.c MAN= gbde.8 -DPADD= ${LIBMD} ${LIBUTIL} ${LIBGEOM} -LDADD= -lmd -lutil -lgeom +LIBADD= md util geom template.c: template.txt file2c 'const char template[] = {' ',0};' \ diff --git a/sbin/geom/Makefile b/sbin/geom/Makefile index ced58425c657..19a56360ccce 100644 --- a/sbin/geom/Makefile +++ b/sbin/geom/Makefile @@ -14,8 +14,7 @@ MAN= WARNS?= 2 CFLAGS+=-I${.CURDIR} -I${.CURDIR}/core -DSTATIC_GEOM_CLASSES -DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} -LDADD= -lgeom -lsbuf -lbsdxml -lutil +LIBADD= geom util .include diff --git a/sbin/geom/class/eli/Makefile b/sbin/geom/class/eli/Makefile index 119566876d71..f8e453dc616c 100644 --- a/sbin/geom/class/eli/Makefile +++ b/sbin/geom/class/eli/Makefile @@ -8,8 +8,7 @@ SRCS+= g_eli_key.c SRCS+= pkcs5v2.c SRCS+= sha2.c -DPADD= ${LIBMD} ${LIBCRYPTO} -LDADD= -lmd -lcrypto +LIBADD= md crypto WARNS?= 3 diff --git a/sbin/geom/class/journal/Makefile b/sbin/geom/class/journal/Makefile index 2db8d3002734..0e1a38ea6dc4 100644 --- a/sbin/geom/class/journal/Makefile +++ b/sbin/geom/class/journal/Makefile @@ -5,8 +5,7 @@ GEOM_CLASS= journal SRCS+= geom_journal_ufs.c -DPADD= ${LIBMD} ${LIBUFS} -LDADD= -lmd -lufs +LIBADD= ufs md CFLAGS+=-I${.CURDIR}/../../../../sys diff --git a/sbin/geom/class/mirror/Makefile b/sbin/geom/class/mirror/Makefile index e38d617b6da5..ce7ee6466326 100644 --- a/sbin/geom/class/mirror/Makefile +++ b/sbin/geom/class/mirror/Makefile @@ -4,7 +4,6 @@ GEOM_CLASS= mirror -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/sbin/geom/class/part/Makefile b/sbin/geom/class/part/Makefile index 341cd42b8c97..4b67de4ef415 100644 --- a/sbin/geom/class/part/Makefile +++ b/sbin/geom/class/part/Makefile @@ -4,7 +4,6 @@ GEOM_CLASS= part -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/sbin/geom/class/raid/Makefile b/sbin/geom/class/raid/Makefile index 743f690f0fd9..07d71403d48f 100644 --- a/sbin/geom/class/raid/Makefile +++ b/sbin/geom/class/raid/Makefile @@ -4,7 +4,6 @@ GEOM_CLASS= raid -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/sbin/geom/class/raid3/Makefile b/sbin/geom/class/raid3/Makefile index d2405d4b4f5d..74e12455a432 100644 --- a/sbin/geom/class/raid3/Makefile +++ b/sbin/geom/class/raid3/Makefile @@ -4,7 +4,6 @@ GEOM_CLASS= raid3 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/sbin/geom/core/Makefile b/sbin/geom/core/Makefile index 64edc793a95e..0636d037a358 100644 --- a/sbin/geom/core/Makefile +++ b/sbin/geom/core/Makefile @@ -11,7 +11,6 @@ NO_SHARED=NO CFLAGS+= -DGEOM_CLASS_DIR=\"${GEOM_CLASS_DIR}\" CFLAGS+= -I${.CURDIR}/../../../sys -I${.CURDIR} -I${.CURDIR}/.. -DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} -LDADD= -lgeom -lsbuf -lbsdxml -lutil +LIBADD= geom util .include diff --git a/sbin/ggate/ggatec/Makefile b/sbin/ggate/ggatec/Makefile index 4d8917f3164c..e228feaf471a 100644 --- a/sbin/ggate/ggatec/Makefile +++ b/sbin/ggate/ggatec/Makefile @@ -10,7 +10,6 @@ CFLAGS+= -DMAX_SEND_SIZE=32768 CFLAGS+= -DLIBGEOM CFLAGS+= -I${.CURDIR}/../shared -DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} ${LIBPTHREAD} -LDADD= -lgeom -lsbuf -lbsdxml -lutil -lpthread +LIBADD= geom util pthread .include diff --git a/sbin/ggate/ggated/Makefile b/sbin/ggate/ggated/Makefile index 4e7708ebffa3..af5c9bdf796a 100644 --- a/sbin/ggate/ggated/Makefile +++ b/sbin/ggate/ggated/Makefile @@ -6,8 +6,7 @@ PROG= ggated MAN= ggated.8 SRCS= ggated.c ggate.c -DPADD= ${LIBPTHREAD} -LDADD= -lpthread +LIBADD= pthread CFLAGS+= -I${.CURDIR}/../shared diff --git a/sbin/ggate/ggatel/Makefile b/sbin/ggate/ggatel/Makefile index 604a75480313..be88bd496c36 100644 --- a/sbin/ggate/ggatel/Makefile +++ b/sbin/ggate/ggatel/Makefile @@ -9,7 +9,6 @@ SRCS= ggatel.c ggate.c CFLAGS+= -DLIBGEOM CFLAGS+= -I${.CURDIR}/../shared -DPADD= ${LIBGEOM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} -LDADD= -lgeom -lsbuf -lbsdxml -lutil +LIBADD= geom util .include diff --git a/sbin/growfs/Makefile b/sbin/growfs/Makefile index 025771fa0370..1f7422e6d4a9 100644 --- a/sbin/growfs/Makefile +++ b/sbin/growfs/Makefile @@ -19,11 +19,10 @@ CFLAGS+=-I${.CURDIR}/../mount SRCS+= debug.c .endif -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .if ${MK_TESTS} != "no" SUBDIR+= tests .endif -.include +.include diff --git a/sbin/gvinum/Makefile b/sbin/gvinum/Makefile index 1b5f948ce893..0e56920d9cee 100644 --- a/sbin/gvinum/Makefile +++ b/sbin/gvinum/Makefile @@ -7,8 +7,7 @@ MAN= gvinum.8 WARNS?= 2 CFLAGS+= -I${.CURDIR}/../../sys -I${DESTDIR}/${INCLUDEDIR}/edit -DPADD= ${LIBEDIT} ${LIBTERMCAPW} ${LIBDEVSTAT} ${LIBKVM} ${LIBGEOM} -LDADD= -ledit -ltermcapw -ldevstat -lkvm -lgeom +LIBADD= edit geom .PATH: ${.CURDIR}/../../sys/geom/vinum diff --git a/sbin/hastctl/Makefile b/sbin/hastctl/Makefile index 89b972e56705..41d443d32783 100644 --- a/sbin/hastctl/Makefile +++ b/sbin/hastctl/Makefile @@ -32,11 +32,9 @@ CFLAGS+=-DINET6 CFLAGS+=-DYY_NO_UNPUT CFLAGS+=-DYY_NO_INPUT -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto CFLAGS+=-DHAVE_CRYPTO .endif diff --git a/sbin/hastd/Makefile b/sbin/hastd/Makefile index 3604b5bab41d..e3fed8d0b522 100644 --- a/sbin/hastd/Makefile +++ b/sbin/hastd/Makefile @@ -30,11 +30,9 @@ CFLAGS+=-DINET CFLAGS+=-DINET6 .endif -DPADD= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} ${LIBPTHREAD} ${LIBUTIL} -LDADD= -lgeom -lbsdxml -lsbuf -lpthread -lutil +LIBADD= geom pthread util .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto CFLAGS+=-DHAVE_CRYPTO .endif diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index 8aba6b466255..885f8a9922bd 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -35,12 +35,10 @@ SRCS+= ifgre.c # GRE keys etc SRCS+= ifgif.c # GIF reversed header workaround SRCS+= sfp.c # SFP/SFP+ information -DPADD+= ${LIBM} -LDADD+= -lm +LIBADD+= m SRCS+= ifieee80211.c regdomain.c # SIOC[GS]IEEE80211 support -DPADD+= ${LIBBSDXML} ${LIBSBUF} -LDADD+= -lbsdxml -lsbuf +LIBADD+= bsdxml sbuf SRCS+= carp.c # SIOC[GS]VH support SRCS+= ifgroup.c # ... @@ -59,8 +57,7 @@ CFLAGS+= -DINET .endif .if ${MK_JAIL} != "no" && !defined(RELEASE_CRUNCH) && !defined(RESCUE) CFLAGS+= -DJAIL -DPADD+= ${LIBJAIL} -LDADD+= -ljail +LIBADD+= jail .endif MAN= ifconfig.8 diff --git a/sbin/init/Makefile b/sbin/init/Makefile index 7497a4b54fd7..6e9c0fc99c67 100644 --- a/sbin/init/Makefile +++ b/sbin/init/Makefile @@ -6,8 +6,7 @@ MAN= init.8 PRECIOUSPROG= INSTALLFLAGS=-b -B.bak CFLAGS+=-DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT -DPADD= ${LIBUTIL} ${LIBCRYPT} -LDADD= -lutil -lcrypt +LIBADD= util crypt NO_SHARED?= YES diff --git a/sbin/ipf/Makefile.inc b/sbin/ipf/Makefile.inc index 2d7d7b1c71bf..79bdb8e378db 100644 --- a/sbin/ipf/Makefile.inc +++ b/sbin/ipf/Makefile.inc @@ -18,9 +18,7 @@ CFLAGS+= -DUSE_INET6 CFLAGS+= -DNOINET6 .endif -LIBIPF= ${.OBJDIR}/../libipf/libipf.a -DPADD+= ${LIBIPF} ${LIBKVM} -LDADD+= ${LIBIPF} -lkvm +LIBADD+= ipf CLEANFILES+= y.tab.c y.tab.h diff --git a/sbin/ipf/ipf/Makefile b/sbin/ipf/ipf/Makefile index c3938c63af61..3ffd2b272489 100644 --- a/sbin/ipf/ipf/Makefile +++ b/sbin/ipf/ipf/Makefile @@ -35,8 +35,7 @@ ipf_l.h: lexer.h LIBIPF_SRCS!= cd ${.CURDIR}/../libipf && ${MAKE} -V SRCS SRCS+= ${LIBIPF_SRCS} .else -DPADD+= ${LIBPCAP} -LDADD+= -lpcap +LIBADD+= pcap .endif .include diff --git a/sbin/ipf/ipfstat/Makefile b/sbin/ipf/ipfstat/Makefile index a33c5df38d8f..14823cf5110c 100644 --- a/sbin/ipf/ipfstat/Makefile +++ b/sbin/ipf/ipfstat/Makefile @@ -5,7 +5,6 @@ NOGCCERROR= # defined PROG= ipfstat SRCS= ipfstat.c MAN= ipfstat.8 -DPADD+= ${LIBCURSES} -LDADD+= -lcurses +LIBADD+= ncursesw .include diff --git a/sbin/ipf/ipsend/Makefile b/sbin/ipf/ipsend/Makefile index 4ae4c3441bbb..176cb106baff 100644 --- a/sbin/ipf/ipsend/Makefile +++ b/sbin/ipf/ipsend/Makefile @@ -8,8 +8,7 @@ PROG= ipsend SRCS= ipsend.c ip.c ipsopt.c iplang_y.c iplang_l.l sbpf.c \ sock.c 44arp.c MAN= ipsend.1 ipsend.5 -DPADD+= ${LIBL} -LDADD+= -ll +LIBADD+= l CFLAGS+= -I${NETBSDSRCDIR}/dist/ipf/ipsend CFLAGS+= -I${NETBSDSRCDIR}/dist/ipf/iplang diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile index 9eb4511fb3c9..efd99fcdf316 100644 --- a/sbin/ipfw/Makefile +++ b/sbin/ipfw/Makefile @@ -11,8 +11,7 @@ SRCS+= altq.c CFLAGS+=-DPF .endif -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util MAN= ipfw.8 .include diff --git a/sbin/iscontrol/Makefile b/sbin/iscontrol/Makefile index 9bdc29bc5b70..a79233fdcfa5 100644 --- a/sbin/iscontrol/Makefile +++ b/sbin/iscontrol/Makefile @@ -2,8 +2,7 @@ SRCS= iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c PROG= iscontrol -DPADD= ${LIBCAM} ${LIBMD} -LDADD= -lcam -lmd +LIBADD= cam md S= ${.CURDIR}/../../sys WARNS?= 3 diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile index eabf129f6b43..a16d46004315 100644 --- a/sbin/md5/Makefile +++ b/sbin/md5/Makefile @@ -16,7 +16,6 @@ MLINKS= md5.1 rmd160.1 \ NO_WMISSING_VARIABLE_DECLARATIONS= WFORMAT?= 1 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/sbin/mdconfig/Makefile b/sbin/mdconfig/Makefile index 69a688cdc389..6be9129144e7 100644 --- a/sbin/mdconfig/Makefile +++ b/sbin/mdconfig/Makefile @@ -5,8 +5,7 @@ PROG= mdconfig MAN= mdconfig.8 -DPADD= ${LIBUTIL} ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} -LDADD= -lutil -lgeom -lbsdxml -lsbuf +LIBADD= util geom .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/sbin/mdconfig/tests/Makefile b/sbin/mdconfig/tests/Makefile index 17284bb6ee22..08a9e47e90dc 100644 --- a/sbin/mdconfig/tests/Makefile +++ b/sbin/mdconfig/tests/Makefile @@ -2,12 +2,9 @@ TESTSDIR= ${TESTSBASE}/sbin/mdconfig -TAP_TESTS_SH= legacy_test -TAP_TESTS_SH_SED_legacy_test= 's,__PERL__,${TAP_PERL_INTERPRETER},g' -TEST_METADATA.legacy_test+= required_programs="${TAP_PERL_INTERPRETER}" +ATF_TESTS_SH= mdconfig_test -FILESDIR= ${TESTSDIR} -FILES= mdconfig.test -FILES+= run.pl + +TEST_METADATA.mdconfig_test+= required_user="root" .include diff --git a/sbin/mdconfig/tests/legacy_test.sh b/sbin/mdconfig/tests/legacy_test.sh deleted file mode 100644 index 728224dbd975..000000000000 --- a/sbin/mdconfig/tests/legacy_test.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2012 Edward Tomasz NapieraÅ‚a -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# - -# This is a wrapper script to run mdconfig.test. - -echo "1..1" - -if [ `whoami` != "root" ]; then - echo "ok 1 # skip You need to be root to run this test." - exit 0 -fi - -TESTDIR=$(dirname $(realpath $0)) - -__PERL__ -w -U $TESTDIR/run.pl $TESTDIR/mdconfig.test > /dev/null - -if [ $? -eq 0 ]; then - echo "ok 1" -else - echo "not ok 1" -fi diff --git a/sbin/mdconfig/tests/mdconfig.test b/sbin/mdconfig/tests/mdconfig.test deleted file mode 100644 index 65d3670b57c3..000000000000 --- a/sbin/mdconfig/tests/mdconfig.test +++ /dev/null @@ -1,231 +0,0 @@ -# Copyright (c) 2012 Edward Tomasz NapieraÅ‚a -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# - -# This is a test for mdconfig(8) functionality. Run it as root: -# -# /usr/src/tools/regression/mdconfig/run /usr/src/tools/regression/mdconfig/mdconfig.test -# -# WARNING: Creates files in unsafe way. - -$ whoami -> root -$ umask 022 -$ truncate -s 1gb xxx - -$ mdconfig -l - -$ mdconfig -af xxx -> md0 - -# This awk thing is to strip the file path. -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Check different valid syntax variations: implicit -a. - -$ mdconfig xxx -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Explicit -t vnode. - -$ mdconfig -a -t vnode -f xxx -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Size for vnodes - smaller than the actual file. - -$ mdconfig -a -t vnode -f xxx -s 128m -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 128M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 134217728 # mediasize in bytes (128M) -> 262144 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Size for vnodes - larger than the actual file. - -$ mdconfig -a -t vnode -f xxx -s 128g -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 128G - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 137438953472 # mediasize in bytes (128G) -> 268435456 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Sector size for vnodes. - -$ mdconfig -a -t vnode -f xxx -S 2048 -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 vnode 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 2048 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 524288 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Malloc type. - -$ mdconfig -a -t malloc -s 1g -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 malloc 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Swap type. - -$ mdconfig -a -t swap -s 1g -> md0 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 swap 1024M - -$ diskinfo -v /dev/md0 | expand -> /dev/md0 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 0 - -# Attaching with a specific unit number. - -$ mdconfig -as 1g -u 42 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md42 swap 1024M - -$ diskinfo -v /dev/md42 | expand -> /dev/md42 -> 512 # sectorsize -> 1073741824 # mediasize in bytes (1.0G) -> 2097152 # mediasize in sectors -> 0 # stripesize -> 0 # stripeoffset -> - -$ mdconfig -du 42 - -# Querying. - -$ mdconfig -as 1g -> md0 -$ mdconfig -as 2g -u 42 - -$ mdconfig -lv | awk '{ print $1, $2, $3 }' -> md0 swap 1024M -> md42 swap 2048M - -$ mdconfig -lvu 0 | awk '{ print $1, $2, $3 }' -> md0 swap 1024M - -$ mdconfig -lvu 42 | awk '{ print $1, $2, $3 }' -> md42 swap 2048M - -$ mdconfig -lvu 24 | awk '{ print $1, $2, $3 }' - -$ mdconfig -du 42 -$ mdconfig -du 0 - -$ rm xxx diff --git a/sbin/mdconfig/tests/mdconfig_test.sh b/sbin/mdconfig/tests/mdconfig_test.sh new file mode 100755 index 000000000000..d12e565db4aa --- /dev/null +++ b/sbin/mdconfig/tests/mdconfig_test.sh @@ -0,0 +1,281 @@ +# Copyright (c) 2012 Edward Tomasz NapieraÅ‚a +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +check_diskinfo() +{ + local md=$1 + local mediasize_in_bytes=$2 + local mediasize_in_sectors=$3 + local sectorsize=${4:-512} + local stripesize=${5:-0} + local stripeoffset=${6:-0} + + atf_check -s exit:0 \ + -o match:"/dev/$md *$sectorsize *$mediasize_in_bytes *$mediasize_in_sectors *$stripesize *$stripeoffset" \ + -x "diskinfo /dev/$md | expand" +} + +cleanup_common() +{ + if [ -f mdconfig.out ]; then + mdconfig -d -u $(sed -e 's/md//' mdconfig.out) + fi +} + +atf_test_case attach_vnode_non_explicit_type cleanup +attach_vnode_non_explicit_type_head() +{ + atf_set "descr" "Tests out -a / -f without -t" +} +attach_vnode_non_explicit_type_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx" + atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig -af xxx' + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "2097152" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_non_explicit_type_cleanup() +{ + cleanup_common +} + +atf_test_case attach_vnode_implicit_a_f cleanup +attach_vnode_implicit_a_f_head() +{ + atf_set "descr" "Tests out implied -a / -f without -t" +} +attach_vnode_implicit_a_f_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx" + atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig xxx' + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "2097152" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_implicit_a_f_cleanup() +{ + cleanup_common +} + +atf_test_case attach_vnode_explicit_type cleanup +attach_vnode_explicit_type_head() +{ + atf_set "descr" "Tests out implied -a / -f with -t vnode" +} +attach_vnode_explicit_type_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx" + atf_check -s exit:0 -o save:mdconfig.out -x 'mdconfig -af xxx -t vnode' + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "2097152" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_explicit_type_cleanup() +{ + [ -f mdconfig.out ] && mdconfig -d -u $(sed -e 's/md//' mdconfig.out) + rm -f mdconfig.out xxx +} + +atf_test_case attach_vnode_smaller_than_file cleanup +attach_vnode_smaller_than_file_head() +{ + atf_set "descr" "Tests mdconfig -s with size less than the file size" +} +attach_vnode_smaller_than_file_body() +{ + local md + local size_in_mb=128 + + atf_check -s exit:0 -x "truncate -s 1024m xxx" + atf_check -s exit:0 -o save:mdconfig.out \ + -x "mdconfig -af xxx -s ${size_in_mb}m" + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "134217728" "262144" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_smaller_than_file_cleanup() +{ + cleanup_common +} + +atf_test_case attach_vnode_larger_than_file cleanup +attach_vnode_larger_than_file_head() +{ + atf_set "descr" "Tests mdconfig -s with size greater than the file size" +} +attach_vnode_larger_than_file_body() +{ + local md + local size_in_gb=128 + + atf_check -s exit:0 -x "truncate -s 1024m xxx" + atf_check -s exit:0 -o save:mdconfig.out \ + -x "mdconfig -af xxx -s ${size_in_gb}g" + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "137438953472" "268435456" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_gb}G$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_larger_than_file_cleanup() +{ + cleanup_common +} + +atf_test_case attach_vnode_sector_size cleanup +attach_vnode_sector_size_head() +{ + atf_set "descr" "Tests mdconfig -s with size greater than the file size" +} +attach_vnode_sector_size_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -x "truncate -s ${size_in_mb}m xxx" + atf_check -s exit:0 -o save:mdconfig.out \ + -x "mdconfig -af xxx -S 2048" + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "524288" "2048" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md vnode ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_vnode_sector_size_cleanup() +{ + cleanup_common +} + +atf_test_case attach_malloc cleanup +attach_malloc_head() +{ + atf_set "descr" "Tests mdconfig with -t malloc" +} +attach_malloc_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -o save:mdconfig.out \ + -x 'mdconfig -a -t malloc -s 1g' + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "2097152" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md malloc ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_malloc_cleanup() +{ + cleanup_common +} + +atf_test_case attach_swap cleanup +attach_swap_head() +{ + atf_set "descr" "Tests mdconfig with -t swap" +} +attach_swap_body() +{ + local md + local size_in_mb=1024 + + atf_check -s exit:0 -o save:mdconfig.out \ + -x 'mdconfig -a -t swap -s 1g' + md=$(cat mdconfig.out) + atf_check -s exit:0 -o match:'^md[0-9]+$' -x "echo $md" + check_diskinfo "$md" "1073741824" "2097152" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md swap ${size_in_mb}M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_swap_cleanup() +{ + cleanup_common +} + +atf_test_case attach_with_specific_unit_number cleanup +attach_with_specific_unit_number_head() +{ + atf_set "descr" "Tests mdconfig with a unit specified by -u" +} +attach_with_specific_unit_number_body() +{ + local md_unit=99 + local size_in_mb=10 + + local md="md${md_unit}" + + echo "$md" > mdconfig.out + + atf_check -s exit:0 -o empty \ + -x "mdconfig -a -t malloc -s ${size_in_mb}m -u $md_unit" + check_diskinfo "$md" "10485760" "20480" + # This awk strips the file path. + atf_check -s exit:0 -o match:"^$md malloc "$size_in_mb"M$" \ + -x "mdconfig -lv | awk '\$1 == \"$md\" { print \$1, \$2, \$3 }'" +} +attach_with_specific_unit_number_cleanup() +{ + cleanup_common +} + +atf_init_test_cases() +{ + atf_add_test_case attach_vnode_non_explicit_type + atf_add_test_case attach_vnode_explicit_type + atf_add_test_case attach_vnode_smaller_than_file + atf_add_test_case attach_vnode_larger_than_file + atf_add_test_case attach_vnode_sector_size + atf_add_test_case attach_malloc + atf_add_test_case attach_swap + atf_add_test_case attach_with_specific_unit_number +} diff --git a/sbin/mdconfig/tests/run.pl b/sbin/mdconfig/tests/run.pl deleted file mode 100644 index 383f47e62397..000000000000 --- a/sbin/mdconfig/tests/run.pl +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/perl -w -U - -# Copyright (c) 2007, 2008 Andreas Gruenbacher. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions, and the following disclaimer, -# without modification, immediately at the beginning of the file. -# 2. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# Alternatively, this software may be distributed under the terms of the -# GNU Public License ("GPL"). -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR -# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# - -# -# Possible improvements: -# -# - distinguish stdout and stderr output -# - add environment variable like assignments -# - run up to a specific line -# - resume at a specific line -# - -use strict; -use FileHandle; -use Getopt::Std; -use POSIX qw(isatty setuid getcwd); -use vars qw($opt_l $opt_v); - -no warnings qw(taint); - -$opt_l = ~0; # a really huge number -getopts('l:v'); - -my ($OK, $FAILED) = ("ok", "failed"); -if (isatty(fileno(STDOUT))) { - $OK = "\033[32m" . $OK . "\033[m"; - $FAILED = "\033[31m\033[1m" . $FAILED . "\033[m"; -} - -sub exec_test($$); -sub process_test($$$$); - -my ($prog, $in, $out) = ([], [], []); -my $prog_line = 0; -my ($tests, $failed) = (0,0); -my $lineno; -my $width = ($ENV{COLUMNS} || 80) >> 1; - -for (;;) { - my $line = <>; $lineno++; - if (defined $line) { - # Substitute %VAR and %{VAR} with environment variables. - $line =~ s[%(\w+)][$ENV{$1}]eg; - $line =~ s[%{(\w+)}][$ENV{$1}]eg; - } - if (defined $line) { - if ($line =~ s/^\s*< ?//) { - push @$in, $line; - } elsif ($line =~ s/^\s*> ?//) { - push @$out, $line; - } else { - process_test($prog, $prog_line, $in, $out); - last if $prog_line >= $opt_l; - - $prog = []; - $prog_line = 0; - } - if ($line =~ s/^\s*\$ ?//) { - $prog = [ map { s/\\(.)/$1/g; $_ } split /(? @$result) ? @$out : @$result; - for (my $n=0; $n < $nmax; $n++) { - my $use_re; - if (defined $out->[$n] && $out->[$n] =~ /^~ /) { - $use_re = 1; - $out->[$n] =~ s/^~ //g; - } - - if (!defined($out->[$n]) || !defined($result->[$n]) || - (!$use_re && $result->[$n] ne $out->[$n]) || - ( $use_re && $result->[$n] !~ /^$out->[$n]/)) { - push @good, ($use_re ? '!~' : '!='); - } - else { - push @good, ($use_re ? '=~' : '=='); - } - } - my $good = !(grep /!/, @good); - $tests++; - $failed++ unless $good; - print $good ? $OK : $FAILED, "\n"; - if (!$good || $opt_v) { - for (my $n=0; $n < $nmax; $n++) { - my $l = defined($out->[$n]) ? $out->[$n] : "~"; - chomp $l; - my $r = defined($result->[$n]) ? $result->[$n] : "~"; - chomp $r; - print sprintf("%-" . ($width-3) . "s %s %s\n", - $r, $good[$n], $l); - } - } -} - - -sub su($) { - my ($user) = @_; - - $user ||= "root"; - - my ($login, $pass, $uid, $gid) = getpwnam($user) - or return [ "su: user $user does not exist\n" ]; - my @groups = (); - my $fh = new FileHandle("/etc/group") - or return [ "opening /etc/group: $!\n" ]; - while (<$fh>) { - chomp; - my ($group, $passwd, $gid, $users) = split /:/; - foreach my $u (split /,/, $users) { - push @groups, $gid - if ($user eq $u); - } - } - $fh->close; - - my $groups = join(" ", ($gid, $gid, @groups)); - #print STDERR "[[$groups]]\n"; - $! = 0; # reset errno - $> = 0; - $( = $gid; - $) = $groups; - if ($!) { - return [ "su: $!\n" ]; - } - if ($uid != 0) { - $> = $uid; - #$< = $uid; - if ($!) { - return [ "su: $prog->[1]: $!\n" ]; - } - } - #print STDERR "[($>,$<)($(,$))]"; - return []; -} - - -sub sg($) { - my ($group) = @_; - - my $gid = getgrnam($group) - or return [ "sg: group $group does not exist\n" ]; - my %groups = map { $_ eq $gid ? () : ($_ => 1) } (split /\s/, $)); - - #print STDERR "<<", join("/", keys %groups), ">>\n"; - my $groups = join(" ", ($gid, $gid, keys %groups)); - #print STDERR "[[$groups]]\n"; - $! = 0; # reset errno - if ($> != 0) { - my $uid = $>; - $> = 0; - $( = $gid; - $) = $groups; - $> = $uid; - } else { - $( = $gid; - $) = $groups; - } - if ($!) { - return [ "sg: $!\n" ]; - } - print STDERR "[($>,$<)($(,$))]"; - return []; -} - - -sub exec_test($$) { - my ($prog, $in) = @_; - local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2); - my $needs_shell = (join('', @$prog) =~ /[][|<>"'`\$\*\?]/); - - if ($prog->[0] eq "umask") { - umask oct $prog->[1]; - return []; - } elsif ($prog->[0] eq "cd") { - if (!chdir $prog->[1]) { - return [ "chdir: $prog->[1]: $!\n" ]; - } - $ENV{PWD} = getcwd; - return []; - } elsif ($prog->[0] eq "su") { - return su($prog->[1]); - } elsif ($prog->[0] eq "sg") { - return sg($prog->[1]); - } elsif ($prog->[0] eq "export") { - my ($name, $value) = split /=/, $prog->[1]; - # FIXME: need to evaluate $value, so that things like this will work: - # export dir=$PWD/dir - $ENV{$name} = $value; - return []; - } elsif ($prog->[0] eq "unset") { - delete $ENV{$prog->[1]}; - return []; - } - - pipe *IN2, *OUT - or die "Can't create pipe for reading: $!"; - open *IN_DUP, "<&STDIN" - or *IN_DUP = undef; - open *STDIN, "<&IN2" - or die "Can't duplicate pipe for reading: $!"; - close *IN2; - - open *OUT_DUP, ">&STDOUT" - or die "Can't duplicate STDOUT: $!"; - pipe *IN, *OUT2 - or die "Can't create pipe for writing: $!"; - open *STDOUT, ">&OUT2" - or die "Can't duplicate pipe for writing: $!"; - close *OUT2; - - *STDOUT->autoflush(); - *OUT->autoflush(); - - $SIG{CHLD} = 'IGNORE'; - - if (fork()) { - # Server - if (*IN_DUP) { - open *STDIN, "<&IN_DUP" - or die "Can't duplicate STDIN: $!"; - close *IN_DUP - or die "Can't close STDIN duplicate: $!"; - } - open *STDOUT, ">&OUT_DUP" - or die "Can't duplicate STDOUT: $!"; - close *OUT_DUP - or die "Can't close STDOUT duplicate: $!"; - - foreach my $line (@$in) { - #print "> $line"; - print OUT $line; - } - close *OUT - or die "Can't close pipe for writing: $!"; - - my $result = []; - while () { - #print "< $_"; - if ($needs_shell) { - s#^/bin/sh: line \d+: ##; - } - push @$result, $_; - } - return $result; - } else { - # Client - $< = $>; - close IN - or die "Can't close read end for input pipe: $!"; - close OUT - or die "Can't close write end for output pipe: $!"; - close OUT_DUP - or die "Can't close STDOUT duplicate: $!"; - local *ERR_DUP; - open ERR_DUP, ">&STDERR" - or die "Can't duplicate STDERR: $!"; - open STDERR, ">&STDOUT" - or die "Can't join STDOUT and STDERR: $!"; - - if ($needs_shell) { - exec ('/bin/sh', '-c', join(" ", @$prog)); - } else { - exec @$prog; - } - print STDERR $prog->[0], ": $!\n"; - exit; - } -} - diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile index c4d98f0fc56a..f95085a6cae7 100644 --- a/sbin/mount/Makefile +++ b/sbin/mount/Makefile @@ -6,7 +6,6 @@ SRCS= mount.c mount_fs.c getmntopts.c vfslist.c MAN= mount.8 mount.conf.8 # We do NOT install the getmntopts.3 man page. -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/sbin/mount_cd9660/Makefile b/sbin/mount_cd9660/Makefile index b889174ffa05..c70892c3309e 100644 --- a/sbin/mount_cd9660/Makefile +++ b/sbin/mount_cd9660/Makefile @@ -4,8 +4,7 @@ PROG= mount_cd9660 SRCS= mount_cd9660.c getmntopts.c MAN= mount_cd9660.8 -DPADD= ${LIBKICONV} -LDADD= -lkiconv +LIBADD= kiconv MOUNT= ${.CURDIR}/../mount CFLAGS+= -I${MOUNT} diff --git a/sbin/mount_msdosfs/Makefile b/sbin/mount_msdosfs/Makefile index c3e416af21fc..ede86b4d8674 100644 --- a/sbin/mount_msdosfs/Makefile +++ b/sbin/mount_msdosfs/Makefile @@ -5,8 +5,7 @@ PROG= mount_msdosfs SRCS= mount_msdosfs.c getmntopts.c MAN= mount_msdosfs.8 -DPADD= ${LIBKICONV} -LDADD= -lkiconv +LIBADD= kiconv MOUNT= ${.CURDIR}/../mount CFLAGS+= -I${MOUNT} diff --git a/sbin/mount_udf/Makefile b/sbin/mount_udf/Makefile index 06ad9a768e4c..12d5d5822424 100644 --- a/sbin/mount_udf/Makefile +++ b/sbin/mount_udf/Makefile @@ -3,8 +3,7 @@ PROG= mount_udf SRCS= mount_udf.c getmntopts.c MAN= mount_udf.8 -DPADD= ${LIBKICONV} -LDADD= -lkiconv +LIBADD= kiconv MOUNT= ${.CURDIR}/../mount CFLAGS+= -I${MOUNT} -I${.CURDIR}/../../sys diff --git a/sbin/nandfs/Makefile b/sbin/nandfs/Makefile index 8474b09c522d..5757f8c16886 100644 --- a/sbin/nandfs/Makefile +++ b/sbin/nandfs/Makefile @@ -4,7 +4,6 @@ PROG= nandfs SRCS= nandfs.c lssnap.c mksnap.c rmsnap.c MAN= nandfs.8 -DPADD= ${LIBNANDFS} -LDADD= -lnandfs +LIBADD= nandfs .include diff --git a/sbin/natd/Makefile b/sbin/natd/Makefile index 7d8b3e49eae1..44e5b6f3b0f6 100644 --- a/sbin/natd/Makefile +++ b/sbin/natd/Makefile @@ -3,8 +3,7 @@ PROG = natd SRCS = natd.c icmp.c WARNS?= 3 -LDADD = -lalias -DPADD = ${LIBALIAS} +LIBADD = alias MAN = natd.8 .include diff --git a/sbin/newfs/Makefile b/sbin/newfs/Makefile index d45143ba7a83..83801fd38947 100644 --- a/sbin/newfs/Makefile +++ b/sbin/newfs/Makefile @@ -4,8 +4,7 @@ .PATH: ${.CURDIR}/../../sys/geom PROG= newfs -DPADD= ${LIBUFS} ${LIBUTIL} -LDADD= -lufs -lutil +LIBADD= ufs util SRCS= newfs.c mkfs.c geom_bsd_enc.c WARNS?= 3 diff --git a/sbin/newfs_nandfs/Makefile b/sbin/newfs_nandfs/Makefile index 1d990eddf52c..7a39fbb088e6 100644 --- a/sbin/newfs_nandfs/Makefile +++ b/sbin/newfs_nandfs/Makefile @@ -3,7 +3,6 @@ PROG= newfs_nandfs MAN= newfs_nandfs.8 -LDADD+= -lgeom -DPADD+= ${LIBGEOM} +LIBADD= geom .include diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile index 937f403569dd..de3b7ec5012c 100644 --- a/sbin/pfctl/Makefile +++ b/sbin/pfctl/Makefile @@ -28,7 +28,6 @@ CFLAGS+= -DWITH_INET YFLAGS= -LDADD+= -lm -lmd -DPADD+= ${LIBM} ${LIBMD} +LIBADD= m md .include diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile index fcff8eb45135..49a311e11bb7 100644 --- a/sbin/pflogd/Makefile +++ b/sbin/pflogd/Makefile @@ -8,8 +8,7 @@ MAN= pflogd.8 CFLAGS+=-include ${.CURDIR}/../../lib/libpcap/config.h -LDADD= -lpcap -DPADD= ${LIBPCAP} +LIBADD= pcap WARNS?= 2 diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile index 57f82a8f72b7..533f8b845d7a 100644 --- a/sbin/ping/Makefile +++ b/sbin/ping/Makefile @@ -8,19 +8,16 @@ MAN= ping.8 BINOWN= root BINMODE=4555 WARNS?= 3 -DPADD= ${LIBM} -LDADD= -lm +LIBADD= m .if ${MK_CASPER} != "no" && !defined(RESCUE) -DPADD+= ${LIBCAPSICUM} ${LIBNV} -LDADD+= -lcapsicum -lnv +LIBADD+= capsicum CFLAGS+=-DHAVE_LIBCAPSICUM .endif .if !defined(RELEASE_CRUNCH) CFLAGS+=-DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec +LIBADD+= ipsec .endif .include diff --git a/sbin/ping6/Makefile b/sbin/ping6/Makefile index e40dc6eb9393..35a76e47f853 100644 --- a/sbin/ping6/Makefile +++ b/sbin/ping6/Makefile @@ -10,7 +10,6 @@ WARNS?= 3 BINOWN= root BINMODE=4555 -LDADD= -lipsec -lm -lmd -DPADD= ${LIBIPSEC} ${LIBM} ${LIBMD} +LIBADD= ipsec m md .include diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile index 51a88b7681c7..7be3e3510503 100644 --- a/sbin/quotacheck/Makefile +++ b/sbin/quotacheck/Makefile @@ -5,8 +5,7 @@ PROG= quotacheck SRCS= quotacheck.c preen.c fsutil.c utilities.c WARNS?= 2 MAN= quotacheck.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .PATH: ${.CURDIR}/../fsck ${.CURDIR}/../fsck_ffs diff --git a/sbin/rcorder/Makefile b/sbin/rcorder/Makefile index b71aa4b83d37..50e797f4cc43 100644 --- a/sbin/rcorder/Makefile +++ b/sbin/rcorder/Makefile @@ -5,8 +5,7 @@ PROG= rcorder SRCS= ealloc.c hash.c rcorder.c MAN= rcorder.8 -LDADD= -lutil -DPADD= ${LIBUTIL} +LIBADD= util # XXX hack for make's hash.[ch] CFLAGS+= -DORDER -I. diff --git a/sbin/routed/Makefile b/sbin/routed/Makefile index 8f2a8193318e..2308722c7191 100644 --- a/sbin/routed/Makefile +++ b/sbin/routed/Makefile @@ -5,8 +5,7 @@ PROG= routed MAN= routed.8 SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c WARNS?= 3 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md SUBDIR= rtquery diff --git a/sbin/routed/rtquery/Makefile b/sbin/routed/rtquery/Makefile index e5d0f5a65203..4df7dc29ace3 100644 --- a/sbin/routed/rtquery/Makefile +++ b/sbin/routed/rtquery/Makefile @@ -4,8 +4,7 @@ PROG= rtquery MAN= rtquery.8 -LDADD= -lmd -DPADD= ${LIBMD} +LIBADD= md WARNS?= 3 NO_WARRAY_BOUNDS= diff --git a/sbin/savecore/Makefile b/sbin/savecore/Makefile index f25745826029..e07a81532f87 100644 --- a/sbin/savecore/Makefile +++ b/sbin/savecore/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ PROG= savecore -DPADD= ${LIBZ} -LDADD= -lz +LIBADD= z MAN= savecore.8 .include diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile index bd04f07c1eb4..e974af5f0b15 100644 --- a/sbin/setkey/Makefile +++ b/sbin/setkey/Makefile @@ -37,8 +37,7 @@ WARNS?= 1 CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../lib/libipsec YFLAGS= -d -DPADD= ${LIBL} ${LIBY} -LDADD= -ll -ly +LIBADD= l y CLEANFILES= y.tab.c y.tab.h key_test.o keytest @@ -55,8 +54,7 @@ CFLAGS+= -DIPSEC_DEBUG -DYY_NO_UNPUT CFLAGS+= -DINET6 .endif CFLAGS+= -I. -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec +LIBADD+= ipsec CLEANFILES+= scriptdump y.tab.h #SCRIPTS= scriptdump diff --git a/sbin/sunlabel/Makefile b/sbin/sunlabel/Makefile index ed64bee5809c..21ccfd751a68 100644 --- a/sbin/sunlabel/Makefile +++ b/sbin/sunlabel/Makefile @@ -11,8 +11,7 @@ LINKS= ${BINDIR}/sunlabel ${BINDIR}/disklabel MLINKS= sunlabel.8 disklabel.8 .endif -DPADD= ${LIBGEOM} -LDADD= -lgeom +LIBADD= geom .include diff --git a/sbin/swapon/Makefile b/sbin/swapon/Makefile index 6f8e8df2e5a6..e9074be9c433 100644 --- a/sbin/swapon/Makefile +++ b/sbin/swapon/Makefile @@ -8,7 +8,6 @@ LINKS+= ${BINDIR}/swapon ${BINDIR}/swapctl MLINKS= swapon.8 swapoff.8 MLINKS+=swapon.8 swapctl.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/sbin/tunefs/Makefile b/sbin/tunefs/Makefile index d5313c445526..07fe3b1ccaa1 100644 --- a/sbin/tunefs/Makefile +++ b/sbin/tunefs/Makefile @@ -2,8 +2,7 @@ # $FreeBSD$ PROG= tunefs -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs MAN= tunefs.8 WARNS= 3 diff --git a/secure/lib/libssh/Makefile b/secure/lib/libssh/Makefile index 36b4d7606de9..725ace8d47f7 100644 --- a/secure/lib/libssh/Makefile +++ b/secure/lib/libssh/Makefile @@ -34,17 +34,13 @@ SRCS+= getrrsetbyname.c LDNSDIR= ${.CURDIR}/../../../contrib/ldns CFLAGS+= -DHAVE_LDNS=1 -I${LDNSDIR} SRCS+= getrrsetbyname-ldns.c -DPADD+= ${LIBLDNS} -LDADD+= ${LDLDNS} -USEPRIVATELIB+= ldns +LIBADD+= ldns .endif CFLAGS+= -I${SSHDIR} -include ssh_namespace.h .if ${MK_KERBEROS_SUPPORT} != "no" CFLAGS+= -include krb5_config.h -DPADD+= ${LIBGSSAPI} ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBCOM_ERR} ${LIBMD} ${LIBROKEN} -LDADD+= -lgssapi -lkrb5 -lhx509 -lasn1 -lcom_err -lmd -lroken .endif .if ${MK_OPENSSH_NONE_CIPHER} != "no" @@ -53,8 +49,7 @@ CFLAGS+= -DNONE_CIPHER_ENABLED NO_LINT= -DPADD+= ${LIBCRYPTO} ${LIBCRYPT} ${LIBZ} -LDADD+= -lcrypto -lcrypt -lz +LIBADD+= crypto crypt z .include diff --git a/secure/lib/libssl/Makefile b/secure/lib/libssl/Makefile index f03eb70a487a..b39858fd2d75 100644 --- a/secure/lib/libssl/Makefile +++ b/secure/lib/libssl/Makefile @@ -21,8 +21,7 @@ SRCS= bio_ssl.c d1_both.c d1_clnt.c d1_enc.c d1_lib.c d1_meth.c d1_pkt.c \ INCS= dtls1.h kssl.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h tls1.h INCSDIR=${INCLUDEDIR}/openssl -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +LIBADD= crypto .include diff --git a/secure/libexec/sftp-server/Makefile b/secure/libexec/sftp-server/Makefile index ebddba95f2fd..3ec21fdfbe50 100644 --- a/secure/libexec/sftp-server/Makefile +++ b/secure/libexec/sftp-server/Makefile @@ -12,9 +12,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -23,9 +21,6 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - .include .PATH: ${SSHDIR} diff --git a/secure/libexec/ssh-keysign/Makefile b/secure/libexec/ssh-keysign/Makefile index f248666baace..9efad92e59ac 100644 --- a/secure/libexec/ssh-keysign/Makefile +++ b/secure/libexec/ssh-keysign/Makefile @@ -8,9 +8,7 @@ MAN= ssh-keysign.8 CFLAGS+=-I${SSHDIR} -include ssh_namespace.h BINMODE=4555 -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -19,8 +17,7 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz +LIBADD+= crypto .include diff --git a/secure/libexec/ssh-pkcs11-helper/Makefile b/secure/libexec/ssh-pkcs11-helper/Makefile index b73416f25dd1..6733048c3b5c 100644 --- a/secure/libexec/ssh-pkcs11-helper/Makefile +++ b/secure/libexec/ssh-pkcs11-helper/Makefile @@ -12,9 +12,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -23,8 +21,7 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz +LIBADD+= crypto .include diff --git a/secure/usr.bin/bdes/Makefile b/secure/usr.bin/bdes/Makefile index 306fc2cfe054..ceadd1202730 100644 --- a/secure/usr.bin/bdes/Makefile +++ b/secure/usr.bin/bdes/Makefile @@ -5,7 +5,6 @@ PROG= bdes WARNS?= 2 -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +LIBADD= crypto .include diff --git a/secure/usr.bin/openssl/Makefile b/secure/usr.bin/openssl/Makefile index 89deb68699ae..ccc1b6f08d7c 100644 --- a/secure/usr.bin/openssl/Makefile +++ b/secure/usr.bin/openssl/Makefile @@ -2,8 +2,7 @@ PROG= openssl -DPADD= ${LIBSSL} ${LIBCRYPTO} -LDADD= -lssl -lcrypto +LIBADD= ssl crypto .if exists(Makefile.man) .include "Makefile.man" diff --git a/secure/usr.bin/scp/Makefile b/secure/usr.bin/scp/Makefile index 1d77d4fd13b1..203fbc304fd7 100644 --- a/secure/usr.bin/scp/Makefile +++ b/secure/usr.bin/scp/Makefile @@ -11,9 +11,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -22,9 +20,6 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - .include .PATH: ${SSHDIR} diff --git a/secure/usr.bin/sftp/Makefile b/secure/usr.bin/sftp/Makefile index 96f9d04132ec..42728be2871b 100644 --- a/secure/usr.bin/sftp/Makefile +++ b/secure/usr.bin/sftp/Makefile @@ -11,9 +11,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} ${LIBEDIT} ${LIBNCURSESW} -LDADD= ${LDSSH} -ledit -lncursesw -USEPRIVATELIB= ssh +LIBADD= ssh edit .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -22,9 +20,6 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - .include .PATH: ${SSHDIR} diff --git a/secure/usr.bin/ssh-add/Makefile b/secure/usr.bin/ssh-add/Makefile index fe8739be2436..ec6ebc13acd0 100644 --- a/secure/usr.bin/ssh-add/Makefile +++ b/secure/usr.bin/ssh-add/Makefile @@ -11,9 +11,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -22,9 +20,6 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - .include .PATH: ${SSHDIR} diff --git a/secure/usr.bin/ssh-agent/Makefile b/secure/usr.bin/ssh-agent/Makefile index b5c98b75a9eb..e263dec0617f 100644 --- a/secure/usr.bin/ssh-agent/Makefile +++ b/secure/usr.bin/ssh-agent/Makefile @@ -11,9 +11,7 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -22,8 +20,7 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz +LIBADD+= crypto .include diff --git a/secure/usr.bin/ssh-keygen/Makefile b/secure/usr.bin/ssh-keygen/Makefile index 62e3927a258b..db8dc7efc5d8 100644 --- a/secure/usr.bin/ssh-keygen/Makefile +++ b/secure/usr.bin/ssh-keygen/Makefile @@ -11,19 +11,13 @@ CFLAGS+=-I${SSHDIR} -include ssh_namespace.h SRCS+= roaming_dummy.c .endif -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 -DPADD+= ${LIBLDNS} -LDADD+= ${LDLDNS} -USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz +LIBADD+= crypto .include diff --git a/secure/usr.bin/ssh-keyscan/Makefile b/secure/usr.bin/ssh-keyscan/Makefile index 44659187c0e7..b6b506063f7a 100644 --- a/secure/usr.bin/ssh-keyscan/Makefile +++ b/secure/usr.bin/ssh-keyscan/Makefile @@ -6,9 +6,7 @@ PROG= ssh-keyscan SRCS= ssh-keyscan.c roaming_dummy.c CFLAGS+=-I${SSHDIR} -include ssh_namespace.h -DPADD= ${LIBSSH} -LDADD= ${LDSSH} -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -17,9 +15,6 @@ CFLAGS+= -DHAVE_LDNS=1 #USEPRIVATELIB+= ldns .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - .include .PATH: ${SSHDIR} diff --git a/secure/usr.bin/ssh/Makefile b/secure/usr.bin/ssh/Makefile index 3c969cdaa3d4..b29ee2ebf136 100644 --- a/secure/usr.bin/ssh/Makefile +++ b/secure/usr.bin/ssh/Makefile @@ -15,29 +15,22 @@ SRCS= ssh.c readconf.c clientloop.c sshtty.c \ # gss-genr.c really belongs in libssh; see src/secure/lib/libssh/Makefile SRCS+= gss-genr.c -DPADD= ${LIBSSH} ${LIBUTIL} -LDADD= ${LDSSH} -lutil -USEPRIVATELIB= ssh +LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 -DPADD+= ${LIBLDNS} -LDADD+= ${LDLDNS} -USEPRIVATELIB+= ldns .endif .if ${MK_KERBEROS_SUPPORT} != "no" CFLAGS+= -include krb5_config.h -DPADD+= ${LIBGSSAPI} -LDADD+= -lgssapi +LIBADD+= gssapi .endif .if ${MK_OPENSSH_NONE_CIPHER} != "no" CFLAGS+= -DNONE_CIPHER_ENABLED .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz +LIBADD+= crypto .if defined(LOCALBASE) CFLAGS+= -DXAUTH_PATH=\"${LOCALBASE}/bin/xauth\" diff --git a/secure/usr.sbin/sshd/Makefile b/secure/usr.sbin/sshd/Makefile index 721531552c52..f2c7e362acd4 100644 --- a/secure/usr.sbin/sshd/Makefile +++ b/secure/usr.sbin/sshd/Makefile @@ -25,9 +25,8 @@ SRCS+= gss-genr.c MAN= sshd.8 sshd_config.5 CFLAGS+=-I${SSHDIR} -include ssh_namespace.h -DPADD= ${LIBSSH} ${LIBUTIL} ${LIBWRAP} ${LIBPAM} -LDADD= ${LDSSH} -lutil -lwrap ${MINUSLPAM} -USEPRIVATELIB= ssh +# pam should always happen before ssh here for static linking +LIBADD= pam ssh util wrap .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 @@ -38,34 +37,19 @@ CFLAGS+= -DHAVE_LDNS=1 .if ${MK_AUDIT} != "no" CFLAGS+= -DUSE_BSM_AUDIT -DHAVE_GETAUDIT_ADDR -DPADD+= ${LIBBSM} -LDADD+= -lbsm +LIBADD+= bsm .endif .if ${MK_KERBEROS_SUPPORT} != "no" CFLAGS+= -include krb5_config.h -DPADD+= ${LIBGSSAPI_KRB5} ${LIBGSSAPI} ${LIBKRB5} ${LIBHX509} ${LIBASN1} \ - ${LIBCOM_ERR} ${LIBROKEN} ${LIBWIND} ${LIBHEIMBASE} ${LIBHEIMIPCC} -LDADD+= -lgssapi_krb5 -lgssapi -lkrb5 -lhx509 -lasn1 \ - -lcom_err -lroken -lwind -lheimbase ${LDHEIMIPCC} +LIBADD+= gssapi_krb5 gssapi krb5 .endif .if ${MK_OPENSSH_NONE_CIPHER} != "no" CFLAGS+= -DNONE_CIPHER_ENABLED .endif -DPADD+= ${LIBCRYPT} ${LIBCRYPTO} ${LIBZ} -LDADD+= -lcrypt -lcrypto -lz - -# Fix the order of NEEDED entries for libthr and libc. The libthr -# needs to interpose libc symbols, leaving the libthr loading as -# dependency of krb causes reversed order and broken interposing. Put -# the threading library last on the linker command line, just before -# the -lc added by a compiler driver. -.if ${MK_KERBEROS_SUPPORT} != "no" -DPADD+= ${LIBPTHREAD} -LDADD+= -lpthread -.endif +LIBADD+= crypto .if defined(LOCALBASE) CFLAGS+= -DXAUTH_PATH=\"${LOCALBASE}/bin/xauth\" diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index fa90a162a532..83c180833451 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,7 +1,7 @@ .\" DO NOT EDIT-- this file is automatically generated. .\" from FreeBSD: head/tools/build/options/makeman 255964 2013-10-01 07:22:04Z des .\" $FreeBSD$ -.Dd October 21, 2014 +.Dd November 26, 2014 .Dt SRC.CONF 5 .Os .Sh NAME @@ -267,17 +267,17 @@ amd64/amd64, arm/arm, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386. Set to not build .Xr cpp 1 . .It Va WITHOUT_CROSS_COMPILER -.\" from FreeBSD: head/tools/build/options/WITHOUT_CROSS_COMPILER 264660 2014-04-18 17:03:58Z imp +.\" from FreeBSD: head/tools/build/options/WITHOUT_CROSS_COMPILER 275138 2014-11-26 20:43:09Z gjb Set to not build any cross compiler in the cross-tools stage of buildworld. If you are compiling a different version of -.Fx +.Fx than what is installed on the system, you will need to provide an alternate compiler with XCC to ensure success. If you are compiling with an identical version of -.Fx +.Fx to the host, this option may be safely used. This option may also be safe when the host version of -.Fx +.Fx is close to the sources being built, but all bets are off if there have been any changes to the toolchain between the versions. When set, it also enforces the following options: @@ -396,8 +396,8 @@ This includes the device tree compiler (dtc) and libfdt support library. Set to not build or install programs for operating floppy disk driver. .It Va WITH_FMAKE -.\" from FreeBSD: head/tools/build/options/WITH_FMAKE 266752 2014-05-27 15:52:27Z gjb -Causes the old FreeBSD +.\" from FreeBSD: head/tools/build/options/WITH_FMAKE 275138 2014-11-26 20:43:09Z gjb +Causes the old FreeBSD .Xr make 1 program to be built and installed as fmake. .It Va WITHOUT_FMTREE @@ -490,8 +490,8 @@ This is the default on platforms where gcc is the system compiler. It is a default setting on arm/armeb, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, powerpc/powerpc, powerpc/powerpc64 and sparc64/sparc64. .It Va WITHOUT_GNU_GREP_COMPAT -.\" from FreeBSD: head/tools/build/options/WITHOUT_GNU_GREP_COMPAT 266752 2014-05-27 15:52:27Z gjb -Set this option to omit the gnu extentions to grep from being included in +.\" from FreeBSD: head/tools/build/options/WITHOUT_GNU_GREP_COMPAT 273421 2014-10-21 20:44:33Z emaste +Set this option to omit the gnu extensions to grep from being included in BSD grep. .It Va WITHOUT_GNU_SUPPORT .\" from FreeBSD: head/tools/build/options/WITHOUT_GNU_SUPPORT 156932 2006-03-21 07:50:50Z ru @@ -531,6 +531,14 @@ Set to not build or install HyperV utilities. .It Va WITHOUT_ICONV .\" from FreeBSD: head/tools/build/options/WITHOUT_ICONV 254919 2013-08-26 17:15:56Z antoine Set to not build iconv as part of libc. +.It Va WITHOUT_INCLUDES +.\" from FreeBSD: head/tools/build/options/WITHOUT_INCLUDES 275138 2014-11-26 20:43:09Z gjb +Set to not install header files. +This option used to be spelled +.Va NO_INCS . +.Bf -symbolic +The option does not work for build targets. +.Ef .It Va WITHOUT_INET .\" from FreeBSD: head/tools/build/options/WITHOUT_INET 221266 2011-04-30 17:58:28Z bz Set to not build programs and libraries related to IPv4 networking. @@ -668,8 +676,8 @@ Set to not build programs that support a legacy PC console; e.g., and .Xr vidcontrol 8 . .It Va WITHOUT_LIB32 -.\" from FreeBSD: head/tools/build/options/WITHOUT_LIB32 156932 2006-03-21 07:50:50Z ru -On amd64, set to not build 32-bit library set and a +.\" from FreeBSD: head/tools/build/options/WITHOUT_LIB32 274664 2014-11-18 17:06:48Z imp +On 64-bit platforms, set to not build 32-bit library set and a .Nm ld-elf32.so.1 runtime linker. .It Va WITHOUT_LIBCPLUSPLUS @@ -938,12 +946,11 @@ This includes .Xr rsh 1 , etc. .It Va WITHOUT_RCS -.\" from FreeBSD: head/tools/build/options/WITHOUT_RCS 271401 2014-09-10 19:00:17Z asomers +.\" from FreeBSD: head/tools/build/options/WITHOUT_RCS 275138 2014-11-26 20:43:09Z gjb Set to not build -.Xr rcs 1 -, -.Xr etcupdate 8 -, and related utilities. +.Xr rcs 1 , +.Xr etcupdate 8 , +and related utilities. .It Va WITHOUT_RESCUE .\" from FreeBSD: head/tools/build/options/WITHOUT_RESCUE 156932 2006-03-21 07:50:50Z ru Set to not build @@ -1047,6 +1054,15 @@ See .Xr tests 7 for more details. This also disables the build of all test-related dependencies, including ATF. +When set, it also enforces the following options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_TESTS_SUPPORT +.El +.It Va WITHOUT_TESTS_SUPPORT +.\" from FreeBSD: head/tools/build/options/WITHOUT_TESTS_SUPPORT 274665 2014-11-18 17:06:50Z imp +Set to disables the build of all test-related dependencies, including ATF. .It Va WITHOUT_TEXTPROC .\" from FreeBSD: head/tools/build/options/WITHOUT_TEXTPROC 183242 2008-09-21 22:02:26Z sam Set to not build @@ -1080,6 +1096,8 @@ When set, it also enforces the following options: .Va WITHOUT_GCC .It .Va WITHOUT_GDB +.It +.Va WITHOUT_INCLUDES .El .It Va WITHOUT_UNBOUND .\" from FreeBSD: head/tools/build/options/WITHOUT_UNBOUND 255597 2013-09-15 14:51:23Z des @@ -1089,6 +1107,9 @@ and related programs. .It Va WITHOUT_USB .\" from FreeBSD: head/tools/build/options/WITHOUT_USB 156932 2006-03-21 07:50:50Z ru Set to not build USB-related programs and libraries. +.It Va WITHOUT_USB_GADGET_EXAMPLES +.\" from FreeBSD: head/tools/build/options/WITHOUT_USB_GADGET_EXAMPLES 274665 2014-11-18 17:06:50Z imp +Set to build USB gadget kernel modules. .It Va WITHOUT_UTMPX .\" from FreeBSD: head/tools/build/options/WITHOUT_UTMPX 231530 2012-02-11 20:28:42Z ed Set to not build user accounting tools such as diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index eef10fcbf95f..2012977bfcb6 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1577,12 +1577,16 @@ MLINKS+=timeout.9 callout.9 \ timeout.9 callout_pending.9 \ timeout.9 callout_reset.9 \ timeout.9 callout_reset_curcpu.9 \ - timeout.9 callout_reset_sbt.9 \ timeout.9 callout_reset_on.9 \ + timeout.9 callout_reset_sbt.9 \ + timeout.9 callout_reset_sbt_curcpu.9 \ timeout.9 callout_reset_sbt_on.9 \ timeout.9 callout_schedule.9 \ timeout.9 callout_schedule_curcpu.9 \ timeout.9 callout_schedule_on.9 \ + timeout.9 callout_schedule_sbt.9 \ + timeout.9 callout_schedule_sbt_curcpu.9 \ + timeout.9 callout_schedule_sbt_on.9 \ timeout.9 callout_stop.9 \ timeout.9 untimeout.9 MLINKS+=ucred.9 cred_update_thread.9 \ diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9 index fad86900512a..7202815a7824 100644 --- a/share/man/man9/timeout.9 +++ b/share/man/man9/timeout.9 @@ -51,6 +51,9 @@ .Nm callout_schedule , .Nm callout_schedule_curcpu , .Nm callout_schedule_on , +.Nm callout_schedule_sbt , +.Nm callout_schedule_sbt_curcpu , +.Nm callout_schedule_sbt_on , .Nm callout_stop , .Nm timeout , .Nm untimeout @@ -106,6 +109,15 @@ struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle); .Ft int .Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu" .Ft int +.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \ +"sbintime_t pr" "int flags" +.Ft int +.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \ +"sbintime_t pr" "int flags" +.Ft int +.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \ +"sbintime_t pr" "int cpu" "int flags" +.Ft int .Fn callout_stop "struct callout *c" .Ft struct callout_handle .Fn timeout "timeout_t *func" "void *arg" "int ticks" @@ -386,21 +398,24 @@ callouts are assigned to CPU 0. The .Fn callout_reset_on , .Fn callout_reset_sbt_on , -and .Fn callout_schedule_on +and +.Fn callout_schedule_sbt_on functions assign the callout to CPU .Fa cpu . The .Fn callout_reset_curcpu , .Fn callout_reset_sbt_curpu , -and .Fn callout_schedule_curcpu +and +.Fn callout_schedule_sbt_curcpu functions assign the callout to the current CPU. The .Fn callout_reset , .Fn callout_reset_sbt , -and .Fn callout_schedule +and +.Fn callout_schedule_sbt functions schedule the callout to execute in the softclock thread of the CPU to which it is currently assigned. .Pp diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree index ad2d52ca9cee..7df15cc83535 100644 --- a/share/misc/bsd-family-tree +++ b/share/misc/bsd-family-tree @@ -296,30 +296,30 @@ FreeBSD 5.2 | | | | | \ | | | | | *--FreeBSD | | | NetBSD 6.1.3 | | | 10.0 | | | | | | - | | | | | | DragonFly 3.6.1 - | | | | | | | - | | | | | | | - | | | | | | DragonFly 3.6.2 - | | | | NetBSD 6.1.4 | | - | | | | | | - | | | | OpenBSD 5.5 | - | | | | | | - | | | | | DragonFly 3.8.0 - | | | | | | - | | | | | | - | | | | | DragonFly 3.8.1 - | | | | | | - | | | | | | - | | | | | DragonFly 3.6.3 - | | | | | | - | FreeBSD | | | | - | 9.3 | | | | - | | | | DragonFly 3.8.2 - | Mac OS X | | | - | 10.10 | | | - | | | | | - | | | | | - | | | | | + | | | | | | | DragonFly 3.6.1 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.6.2 + | | | | | NetBSD 6.1.4 | | + | | | | | | | | + | | | | | | OpenBSD 5.5 | + | | | | | | | | + | | | | | | | DragonFly 3.8.0 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.8.1 + | | | | | | | | + | | | | | | | | + | | | | | | | DragonFly 3.6.3 + | | | | | | | | + | | FreeBSD | | | | | + | | 9.3 | | | | | + | | | | NetBSD 6.1.5 | DragonFly 3.8.2 + | | Mac OS X | | | + | | 10.10 | | | + | | | | OpenBSD 5.6 | + | FreeBSD | | | | + | 10.1 | | | DragonFly 4.0.1 | | | | | | | | | | | | | | | @@ -655,7 +655,11 @@ DragonFly 3.8.1 2014-06-16 [DFB] DragonFly 3.6.3 2014-06-17 [DFB] FreeBSD 9.3 2014-07-05 [FBD] DragonFly 3.8.2 2014-08-08 [DFB] +NetBSD 6.1.5 2014-09-22 [NDB] Mac OS X 10.10 2014-10-16 [APL] +OpenBSD 5.6 2014-11-01 [OBD] +FreeBSD 10.1 2014-11-14 [FBD] +DragonFly 4.0.1 2014-11-25 [DFB] Bibliography ------------------------ diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 44d81586be71..00f0a0adf0cf 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -54,6 +54,7 @@ LIBFIGPAR?= ${DESTDIR}${LIBDIR}/libfigpar.a LIBFL?= "don't use LIBFL, use LIBL" LIBFORM?= ${DESTDIR}${LIBDIR}/libform.a LIBG2C?= ${DESTDIR}${LIBDIR}/libg2c.a +LIBGPIO?= ${DESTDIR}${LIBDIR}/libgpio.a LIBGEOM?= ${DESTDIR}${LIBDIR}/libgeom.a LIBGNUREGEX?= ${DESTDIR}${LIBDIR}/libgnuregex.a LIBGSSAPI?= ${DESTDIR}${LIBDIR}/libgssapi.a @@ -90,33 +91,7 @@ LIBNGATM?= ${DESTDIR}${LIBDIR}/libngatm.a LIBNV?= ${DESTDIR}${LIBDIR}/libnv.a LIBNVPAIR?= ${DESTDIR}${LIBDIR}/libnvpair.a LIBOPIE?= ${DESTDIR}${LIBDIR}/libopie.a - -# The static PAM library doesn't know its secondary dependencies, -# so we have to specify them explicitly. Ths is an unfortunate, -# but necessary departure from testing MK_ flags to define -# values here. LIBPAM?= ${DESTDIR}${LIBDIR}/libpam.a -MINUSLPAM= -lpam -.if defined(LDFLAGS) && !empty(LDFLAGS:M-static) -.if ${MK_KERBEROS} != "no" -LIBPAM+= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBCRYPTO} ${LIBCRYPT} \ - ${LIBROKEN} ${LIBCOM_ERR} -MINUSLPAM+= -lkrb5 -lhx509 -lasn1 -lcrypto -lcrypt -lroken -lcom_err -.endif -LIBPAM+= ${LIBRADIUS} ${LIBTACPLUS} ${LIBCRYPT} \ - ${LIBUTIL} ${LIBOPIE} ${LIBMD} -MINUSLPAM+= -lradius -ltacplus -lcrypt \ - -lutil -lopie -lmd -.if ${MK_OPENSSH} != "no" -LIBPAM+= ${LIBSSH} ${LIBCRYPTO} ${LIBCRYPT} -MINUSLPAM+= -lssh -lcrypto -lcrypt -.endif -.if ${MK_NIS} != "no" -LIBPAM+= ${LIBYPCLNT} -MINUSLPAM+= -lypclnt -.endif -.endif - LIBPANEL?= ${DESTDIR}${LIBDIR}/libpanel.a LIBPCAP?= ${DESTDIR}${LIBDIR}/libpcap.a LIBPJDLOG?= ${DESTDIR}${LIBDIR}/libpjdlog.a diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index 7281c0a6b828..094897d06a1f 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -7,7 +7,273 @@ .error src.libnames.mk cannot be included directly. .endif -ROOTOBJDIR= ${.OBJDIR:S/${.CURDIR}//}${.MAKE.MAKEFILES:M*/src.libnames.mk:H:H:H} +.include + +ROOTSRCDIR= ${.MAKE.MAKEFILES:M*/src.libnames.mk:H:H:H} +ROOTOBJDIR= ${.OBJDIR:S/${.CURDIR}//}${ROOTSRCDIR} +_PRIVATELIBS= \ + atf_c \ + atf_cxx \ + bsdstat \ + heimipcc \ + heimipcs \ + ldns \ + sqlite3 \ + ssh \ + ucl \ + unbound + +_INTERNALIBS= \ + amu \ + bsnmptools \ + cron \ + event \ + fifolog \ + ipf \ + lpr \ + mandoc \ + netbsd \ + ntp \ + ohash \ + opts \ + parse \ + readline \ + sl \ + sm \ + smdb \ + smutil \ + telnet \ + vers + +_LIBRARIES= \ + ${_PRIVATELIBS} \ + ${_INTERNALIBS} \ + alias \ + archive \ + asn1 \ + auditd \ + begemot \ + bluetooth \ + bsdxml \ + bsm \ + bsnmp \ + bz2 \ + c \ + c_pic \ + calendar \ + cam \ + capsicum \ + casper \ + com_err \ + compiler_rt \ + crypt \ + crypto \ + ctf \ + cuse \ + cxxrt \ + devinfo \ + devstat \ + dialog \ + dpv \ + dwarf \ + edit \ + elf \ + execinfo \ + fetch \ + figpar \ + geom \ + gnuregex \ + gssapi \ + gssapi_krb5 \ + hdb \ + heimbase \ + heimntlm \ + heimsqlite \ + hx509 \ + ipsec \ + jail \ + kadm5clnt \ + kadm5srv \ + kafs5 \ + kdc \ + kiconv \ + krb5 \ + kvm \ + l \ + lzma \ + m \ + magic \ + mandoc \ + md \ + memstat \ + mp \ + nandfs \ + ncursesw \ + netgraph \ + ngatm \ + nv \ + opie \ + pam \ + pcap \ + pcsclite \ + pjdlog \ + pmc \ + proc \ + procstat \ + pthread \ + radius \ + readline \ + roken \ + rpcsec_gss \ + rpcsvc \ + rt \ + sbuf \ + sdp \ + sm \ + smb \ + ssl \ + ssp_nonshared \ + stdthreads \ + supcplusplus \ + tacplus \ + termcapw \ + ufs \ + ugidfw \ + ulog \ + usb \ + usbhid \ + util \ + vmmapi \ + wind \ + wrap \ + xo \ + y \ + ypclnt \ + z + +_DP_archive= z bz2 lzma bsdxml +.if ${MK_OPENSSL} != "no" +_DP_archive+= crypto +.else +_DP_archive+= md +.endif +_DP_ssl= crypto +_DP_ssh= crypto crypt +.if ${MK_LDNS} != "no" +_DP_ssh+= ldns z +.endif +_DP_edit= ncursesw +.if ${MK_OPENSSL} != "no" +_DP_bsnmp= crypto +.endif +_DP_grom= bsdxml sbuf +_DP_cam= sbuf +_DP_casper= capsicum nv pjdlog +_DP_capsicum= nv +_DP_pjdlog= util +_DP_opie= md +_DP_usb= pthread +_DP_unbound= pthread +_DP_rt= pthread +.if ${MK_OPENSSL} == "no" +_DP_radius= md +.else +_DP_radius= crypto +.endif +_DP_procstat= kvm util elf +.if ${MK_CXX} == "yes" +.if ${MK_LIBCPLUSPLUS} != "no" +_DP_proc= cxxrt +.else +_DP_proc= supcplusplus +.endif +.endif +.if ${MK_CDDL} != "no" +_DP_proc+= ctf +.endif +_DP_mp= crypto +_DP_memstat= kvm +_DP_magic= z +_DP_ldns= crypto +.if ${MK_OPENSSL} != "no" +_DP_fetch= ssl crypto +.else +_DP_fetch= md +.endif +_DP_execinfo= elf +_DP_dwarf= elf +_DP_dpv= dialog figpar util +_DP_dialog= ncursesw m +_DP_cuse= pthread +_DP_atf_cxx= atf_c +_DP_devstat= kvm +_DP_pam= radius tacplus opie md util +.if ${MK_KERBEROS} != "no" +_DP_pam+= krb5 +.endif +.if ${MK_OPENSSH} != "no" +_DP_pam+= ssh +.endif +.if ${MK_NIS} != "no" +_DP_pam+= ypclnt +.endif +_DP_krb5+= asn1 com_err crypt crypto hx509 roken wind heimbase heimipcc \ + pthread +_DP_gssapi_krb5+= gssapi krb5 crypto roken asn1 com_err +_DP_ucl= m + +# Define spacial cases +LDADD_supcplusplus= -lsupc++ +LDADD_atf_c= -L${LIBATF_CDIR} -latf-c +LDADD_atf_cxx= -L${LIBATF_CXXDIR} -latf-c++ + +.for _l in ${_LIBRARIES} +.if ${_PRIVATELIBS:M${_l}} +LDADD_${_l}_L+= -L${LIB${_l:tu}DIR} +.endif +.if ${_INTERNALIBS:M${_l}} +LDADD_${_l}_L+= -L${LIB${_l:tu}DIR} +.endif +DPADD_${_l}?= ${LIB${_l:tu}} +LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l} +.if defined(_DP_${_l}) && defined(NO_SHARED) +.for _d in ${_DP_${_l}} +DPADD_${_l}+= ${DPADD_${_d}} +LDADD_${_l}+= ${LDADD_${_d}} +.endfor +.endif +.endfor + +DPADD_sqlite3+= ${DPADD_pthread} +LDADD_sqlite3+= ${LDADD_pthread} + +DPADD_atf_cxx+= ${DPADD_atf_c} +LDADD_atf_cxx+= ${LDADD_atf_c} + +DPADD_ipf+= ${DPADD_kvm} +LDADD_ipf+= ${LDADD_kvm} + +# The following depends on libraries which are using pthread +DPADD_hdb+= ${DPADD_pthread} +LDADD_hdb+= ${LDADD_pthread} +DPADD_kadm5srv+= ${DPADD_pthread} +LDADD_kadm5srv+= ${LDADD_pthread} +DPADD_krb5+= ${DPADD_pthread} +LDADD_krb5+= ${LDADD_pthread} +DPADD_gssapi_krb5+= ${DPADD_pthread} +LDADD_gssapi_krb5+= ${LDADD_pthread} + +.for _l in ${LIBADD} +.if ${_PRIVATELIBS:M${_l}} +USEPRIVATELIB+= ${_l} +.endif +DPADD+= ${DPADD_${_l}} +LDADD+= ${LDADD_${_l}} +.endfor + +.if defined(USEPRIVATELIB) +LDFLAGS+= -rpath ${LIBPRIVATEDIR} +.endif LIBATF_CDIR= ${ROOTOBJDIR}/lib/atf/libatf-c LDATF_C?= ${LIBATF_CDIR}/libatf-c.so @@ -18,49 +284,86 @@ LDATF_CXX?= ${LIBATF_CXXDIR}/libatf-c++.so LIBATF_CXX?= ${LIBATF_CXXDIR}/libatf-c++.a LIBBSDSTATDIR= ${ROOTOBJDIR}/lib/libbsdstat -LDBSDSTAT?= ${LIBBSDSTATDIR}/libbsdstat.so LIBBSDSTAT?= ${LIBBSDSTATDIR}/libbsdstat.a LIBEVENTDIR= ${ROOTOBJDIR}/lib/libevent -LDEVENT?= ${LIBEVENTDIR}/libevent.so LIBEVENT?= ${LIBEVENTDIR}/libevent.a LIBHEIMIPCCDIR= ${ROOTOBJDIR}/kerberos5/lib/libheimipcc -LDHEIMIPCC?= ${LIBHEIMIPCCDIR}/libheimipcc.so LIBHEIMIPCC?= ${LIBHEIMIPCCDIR}/libheimipcc.a LIBHEIMIPCSDIR= ${ROOTOBJDIR}/kerberos5/lib/libheimipcs -LDHEIMIPCS?= ${LIBHEIMIPCSDIR}/libheimipcs.so LIBHEIMIPCS?= ${LIBHEIMIPCSDIR}/libheimipcs.a LIBLDNSDIR= ${ROOTOBJDIR}/lib/libldns -LDLDNS?= ${LIBLDNSDIR}/libldns.so LIBLDNS?= ${LIBLDNSDIR}/libldns.a LIBSSHDIR= ${ROOTOBJDIR}/secure/lib/libssh -LDSSH?= ${LIBSSHDIR}/libssh.so LIBSSH?= ${LIBSSHDIR}/libssh.a LIBUNBOUNDDIR= ${ROOTOBJDIR}/lib/libunbound -LDUNBOUND?= ${LIBUNBOUNDDIR}/libunbound.so LIBUNBOUND?= ${LIBUNBOUNDDIR}/libunbound.a LIBUCLDIR= ${ROOTOBJDIR}/lib/libucl -LDUCL?= ${LIBUCLDIR}/libucl.so LIBUCL?= ${LIBUCLDIR}/libucl.a LIBREADLINEDIR= ${ROOTOBJDIR}/gnu/lib/libreadline/readline -LDREADLINE?= ${LIBREADLINEDIR}/libreadline.a LIBREADLINE?= ${LIBREADLINEDIR}/libreadline.a LIBOHASHDIR= ${ROOTOBJDIR}/lib/libohash -LDOHASH?= ${LIBOHASHDIR}/libohash.a LIBOHASH?= ${LIBOHASHDIR}/libohash.a LIBSQLITE3DIR= ${ROOTOBJDIR}/lib/libsqlite3 -LDSQLITE3?= ${LIBSQLITE3DIR}/libsqlite3.so LIBSQLITE3?= ${LIBSQLITE3DIR}/libsqlite3.a LIBMANDOCDIR= ${ROOTOBJDIR}/lib/libmandoc -LDMANDOC?= ${LIBMANDOCDIR}/libmandoc.a LIBMANDOC?= ${LIBMANDOCDIR}/libmandoc.a + +LIBSMDIR= ${ROOTOBJDIR}/lib/libsm +LIBSM?= ${LIBSMDIR}/libsm.a + +LIBSMDBDIR= ${ROOTOBJDIR}/lib/libsmdb +LIBSMDB?= ${LIBSMDBDIR}/libsmdb.a + +LIBSMUTILDIR= ${ROOTOBJDIR}/lib/libsmutil +LIBSMUTIL?= ${LIBSMDBDIR}/libsmutil.a + +LIBNETBSDDIR?= ${ROOTOBJDIR}/lib/libnetbsd +LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd.a + +LIBVERSDIR?= ${ROOTOBJDIR}/kerberos5/lib/libvers +LIBVERS?= ${LIBVERSDIR}/libvers.a + +LIBSLDIR= ${ROOTOBJDIR}/kerberos5/lib/libsl +LIBSL?= ${LIBSLDIR}/libsl.a + +LIBIPFDIR= ${ROOTOBJDIR}/sbin/ipf/libipf +LIBIPF?= ${LIBIPFDIR}/libipf.a + +LIBTELNETDIR= ${ROOTOBJDIR}/lib/libtelnet +LIBTELNET?= ${LIBIPFDIR}/libtelnet.a + +LIBCRONDIR= ${ROOTOBJDIR}/usr.sbin/cron/lib +LIBCRON?= ${LIBCRONDIR}/libcron.a + +LIBNTPDIR= ${ROOTOBJDIR}/usr.sbin/ntp/libntp +LIBNTP?= ${LIBNTPDIR}/libntp.a + +LIBOPTSDIR= ${ROOTOBJDIR}/usr.sbin/ntp/libopts +LIBOTPS?= ${LIBOPTSDIR}/libopts.a + +LIBPARSEDIR= ${ROOTOBJDIR}/usr.sbin/ntp/libparse +LIBPARSE?= ${LIBOPTSDIR}/libparse.a + +LIBLPRDIR= ${ROOTOBJDIR}/usr.sbin/lpr/common_source +LIBLPR?= ${LIBOPTSDIR}/liblpr.a + +LIBFIFOLOGDIR= ${ROOTOBJDIR}/usr.sbin/fifolog/lib +LIBFIFOLOG?= ${LIBOPTSDIR}/libfifolog.a + +LIBBSNMPTOOLSDIR= ${ROOTOBJDIR}/usr.sbin/bsnmpd/tools/libbsnmptools +LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools.a + +LIBAMUDIR= ${ROOTOBJDIR}/usr.sbin/amd/libamu +LIBAMU?= ${LIBAMUDIR}/libamu/libamu.a + diff --git a/sys/amd64/include/asm.h b/sys/amd64/include/asm.h index 429c6a989b27..87272f76fdde 100644 --- a/sys/amd64/include/asm.h +++ b/sys/amd64/include/asm.h @@ -38,7 +38,7 @@ #include -#ifdef __PIC__ +#ifdef PIC #define PIC_PLT(x) x@PLT #define PIC_GOT(x) x@GOTPCREL(%rip) #else diff --git a/sys/arm/altera/socfpga/files.socfpga b/sys/arm/altera/socfpga/files.socfpga index 7e6b14cc40f8..85c8f5055ed3 100644 --- a/sys/arm/altera/socfpga/files.socfpga +++ b/sys/arm/altera/socfpga/files.socfpga @@ -26,3 +26,5 @@ dev/mmc/host/dwmmc.c optional dwmmc # BERI specific dev/beri/beri_ring.c optional beri_ring dev/beri/beri_mem.c optional beri_mem +dev/beri/virtio/virtio.c optional beri_vtblk +dev/beri/virtio/virtio_block.c optional beri_vtblk diff --git a/sys/arm/altera/socfpga/socfpga_machdep.c b/sys/arm/altera/socfpga/socfpga_machdep.c index 428a9985d5de..988e5ad21fff 100644 --- a/sys/arm/altera/socfpga/socfpga_machdep.c +++ b/sys/arm/altera/socfpga/socfpga_machdep.c @@ -95,6 +95,9 @@ platform_devmap_init(void) /* scu */ arm_devmap_add_entry(0xfff00000, 0x100000); + /* FPGA memory window, 256MB */ + arm_devmap_add_entry(0xd0000000, 0x10000000); + return (0); } diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index d9b42fcedae0..a447353c46c2 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -87,7 +87,7 @@ static struct resource_spec timer_spec[] = { { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */ { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */ - { SYS_RES_IRQ, 3, RF_ACTIVE }, /* Hyp */ + { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, /* Hyp */ { -1, 0 } }; @@ -353,6 +353,8 @@ static devclass_t arm_tmr_devclass; EARLY_DRIVER_MODULE(timer, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(timer, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0, + BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); void DELAY(int usec) diff --git a/sys/arm/conf/SOCKIT-BERI b/sys/arm/conf/SOCKIT-BERI index a19bd8257a5c..fece41c611cf 100644 --- a/sys/arm/conf/SOCKIT-BERI +++ b/sys/arm/conf/SOCKIT-BERI @@ -122,6 +122,8 @@ device spibus # BERI specific device beri_ring device beri_mem +device beri_vtblk +device altera_pio # Ethernet device ether diff --git a/sys/arm/include/asm.h b/sys/arm/include/asm.h index c7188487d0e0..9577001917b2 100644 --- a/sys/arm/include/asm.h +++ b/sys/arm/include/asm.h @@ -104,7 +104,7 @@ #define ASMSTR .asciz -#if defined(__PIC__) +#if defined(PIC) #define PLT_SYM(x) PIC_SYM(x, PLT) #define GOT_SYM(x) PIC_SYM(x, GOT) #define GOT_GET(x,got,sym) \ @@ -131,7 +131,7 @@ #define GOT_INIT(got,gotsym,pclabel) #define GOT_INITSYM(gotsym,pclabel) #define PIC_SYM(x,y) x -#endif /* __PIC__ */ +#endif /* PIC */ #undef __FBSDID #if !defined(lint) && !defined(STRIP_FBSDID) diff --git a/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts b/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts index 793365a24df4..50167385911f 100644 --- a/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts +++ b/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts @@ -38,8 +38,8 @@ model = "Terasic SoCKit"; compatible = "altr,socfpga-cyclone5", "altr,socfpga"; - /* Reserve first page for secondary CPU trampoline code */ - memreserve = < 0x00000000 0x1000 >; + memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */ + < 0x00001000 0x1000 >; /* virtio block */ memory { device_type = "memory"; @@ -69,6 +69,8 @@ }; mmc: dwmmc@ff704000 { + #address-cells = <1>; + #size-cells = <0>; status = "okay"; num-slots = <1>; supports-highspeed; @@ -81,9 +83,34 @@ }; }; - beri_mem: mem@d0000000 { + beri_mem0: mem@d0000000 { compatible = "sri-cambridge,beri-mem"; - reg = <0xd0000000 0x10000000>; + reg = <0xd0000000 0x10000000>; /* 256mb */ + status = "okay"; + }; + + pio0: pio@c0020000 { + compatible = "altr,pio"; + reg = <0xc0020000 0x1000>; /* recv */ + interrupts = < 76 >; + interrupt-parent = <&GIC>; + status = "okay"; + }; + + pio1: pio@c0021000 { + compatible = "altr,pio"; + reg = <0xc0021000 0x1000>; /* send */ + interrupts = < 82 >; /* not in use on arm side */ + interrupt-parent = <&GIC>; + status = "okay"; + }; + + beri_vtblk: vtblk@00001000 { + compatible = "sri-cambridge,beri-vtblk"; + reg = <0x00001000 0x1000>; + pio-recv = <&pio0>; + pio-send = <&pio1>; + beri-mem = <&beri_mem0>; status = "okay"; }; diff --git a/sys/boot/i386/boot2/boot2.c b/sys/boot/i386/boot2/boot2.c index cd384e565894..4e1a83522f14 100644 --- a/sys/boot/i386/boot2/boot2.c +++ b/sys/boot/i386/boot2/boot2.c @@ -323,7 +323,8 @@ load(void) caddr_t p; ufs_ino_t ino; uint32_t addr; - int i, j; + int k; + uint8_t i, j; if (!(ino = lookup(kname))) { if (!ls) @@ -344,7 +345,7 @@ load(void) return; } else if (IS_ELF(hdr.eh)) { fs_off = hdr.eh.e_phoff; - for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { + for (j = k = 0; k < hdr.eh.e_phnum && j < 2; k++) { if (xfsread(ino, ep + j, sizeof(ep[0]))) return; if (ep[j].p_type == PT_LOAD) @@ -394,6 +395,7 @@ parse() const char *cp; unsigned int drv; int c, i, j; + size_t k; while ((c = *arg++)) { if (c == ' ' || c == '\t' || c == '\n') @@ -416,7 +418,7 @@ parse() #if SERIAL } else if (c == 'S') { j = 0; - while ((unsigned int)(i = *arg++ - '0') <= 9) + while ((i = *arg++ - '0') <= 9) j = j * 10 + i; if (j > 0 && i == -'0') { comspeed = j; @@ -479,10 +481,10 @@ parse() ? DRV_HARD : 0) + drv; dsk_meta = 0; } - if ((i = ep - arg)) { - if ((size_t)i >= sizeof(knamebuf)) + if (k = ep - arg) { + if (k >= sizeof(knamebuf)) return -1; - memcpy(knamebuf, arg, i + 1); + memcpy(knamebuf, arg, k + 1); kname = knamebuf; } } @@ -605,8 +607,10 @@ drvread(void *buf, unsigned lba, unsigned nblk) { static unsigned c = 0x2d5c7c2f; - if (!OPT_CHECK(RBX_QUIET)) - printf("%c\b", c = c << 8 | c >> 24); + if (!OPT_CHECK(RBX_QUIET)) { + xputc(c = c << 8 | c >> 24); + xputc('\b'); + } v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.addr = XREADORG; /* call to xread in boot1 */ v86.es = VTOPSEG(buf); diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index ee30d515a46b..075405f55e11 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -4996,23 +4996,13 @@ ctl_config_move_done(union ctl_io *io) { int retval; - retval = CTL_RETVAL_COMPLETE; - - CTL_DEBUG_PRINT(("ctl_config_move_done\n")); - /* - * XXX KDM this shouldn't happen, but what if it does? - */ - if (io->io_hdr.io_type != CTL_IO_SCSI) - panic("I/O type isn't CTL_IO_SCSI!"); + KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, + ("Config I/O type isn't CTL_IO_SCSI (%d)!", io->io_hdr.io_type)); - if ((io->io_hdr.port_status == 0) - && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) - io->io_hdr.status = CTL_SUCCESS; - else if ((io->io_hdr.port_status != 0) - && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)){ + if ((io->io_hdr.port_status != 0) && + ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE || + (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) { /* * For hardware error sense keys, the sense key * specific value is defined to be a retry count, @@ -5025,15 +5015,12 @@ ctl_config_move_done(union ctl_io *io) /*sks_valid*/ 1, /*retry_count*/ io->io_hdr.port_status); - if (io->io_hdr.flags & CTL_FLAG_ALLOCATED) - free(io->scsiio.kern_data_ptr, M_CTL); - ctl_done(io); - goto bailout; } - if (((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) - || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) - || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)) { + if (((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) || + ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE && + (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) || + ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)) { /* * XXX KDM just assuming a single pointer here, and not a * S/G list. If we start using S/G lists for config data, @@ -5041,8 +5028,8 @@ ctl_config_move_done(union ctl_io *io) */ if (io->io_hdr.flags & CTL_FLAG_ALLOCATED) free(io->scsiio.kern_data_ptr, M_CTL); - /* Hopefully the user has already set the status... */ ctl_done(io); + retval = CTL_RETVAL_COMPLETE; } else { /* * XXX KDM now we need to continue data movement. Some @@ -5065,7 +5052,6 @@ ctl_config_move_done(union ctl_io *io) */ retval = ctl_scsiio(&io->scsiio); } -bailout: return (retval); } @@ -5211,14 +5197,12 @@ ctl_scsi_release(struct ctl_scsiio *ctsio) mtx_unlock(&lun->lun_lock); - ctsio->scsi_status = SCSI_STATUS_OK; - ctsio->io_hdr.status = CTL_SUCCESS; - if (ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) { free(ctsio->kern_data_ptr, M_CTL); ctsio->io_hdr.flags &= ~CTL_FLAG_ALLOCATED; } + ctl_set_success(ctsio); ctl_done((union ctl_io *)ctsio); return (CTL_RETVAL_COMPLETE); } @@ -5299,8 +5283,7 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio) lun->flags |= CTL_LUN_RESERVED; lun->res_idx = residx; - ctsio->scsi_status = SCSI_STATUS_OK; - ctsio->io_hdr.status = CTL_SUCCESS; + ctl_set_success(ctsio); bailout: mtx_unlock(&lun->lun_lock); @@ -5610,8 +5593,7 @@ ctl_format(struct ctl_scsiio *ctsio) lun->flags &= ~CTL_LUN_INOPERABLE; mtx_unlock(&lun->lun_lock); - ctsio->scsi_status = SCSI_STATUS_OK; - ctsio->io_hdr.status = CTL_SUCCESS; + ctl_set_success(ctsio); bailout: if (ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) { @@ -5684,9 +5666,9 @@ ctl_read_buffer(struct ctl_scsiio *ctsio) ctsio->kern_data_resid = 0; ctsio->kern_rel_offset = 0; ctsio->kern_sg_entries = 0; + ctl_set_success(ctsio); ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -5749,8 +5731,8 @@ ctl_write_buffer(struct ctl_scsiio *ctsio) return (CTL_RETVAL_COMPLETE); } + ctl_set_success(ctsio); ctl_done((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -6873,12 +6855,10 @@ ctl_mode_sense(struct ctl_scsiio *ctsio) } } - ctsio->scsi_status = SCSI_STATUS_OK; - + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -7028,11 +7008,10 @@ ctl_log_sense(struct ctl_scsiio *ctsio) memcpy(header + 1, page_index->page_data, page_index->page_len); - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -7087,12 +7066,10 @@ ctl_read_capacity(struct ctl_scsiio *ctsio) */ scsi_ulto4b(lun->be_lun->blocksize, data->length); - ctsio->scsi_status = SCSI_STATUS_OK; - + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -7150,12 +7127,10 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio) if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) data->lalba_lbp[0] |= SRC16_LBPME | SRC16_LBPRZ; - ctsio->scsi_status = SCSI_STATUS_OK; - + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -7215,7 +7190,7 @@ ctl_read_defect(struct ctl_scsiio *ctsio) scsi_ulto4b(0, data12->length); } - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -7358,15 +7333,9 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio) } mtx_unlock(&softc->ctl_lock); + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - - CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n", - ctsio->kern_data_ptr[0], ctsio->kern_data_ptr[1], - ctsio->kern_data_ptr[2], ctsio->kern_data_ptr[3], - ctsio->kern_data_ptr[4], ctsio->kern_data_ptr[5], - ctsio->kern_data_ptr[6], ctsio->kern_data_ptr[7])); - ctl_datamove((union ctl_io *)ctsio); return(retval); } @@ -7530,9 +7499,9 @@ ctl_report_supported_opcodes(struct ctl_scsiio *ctsio) break; } + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return(retval); } @@ -7574,9 +7543,9 @@ ctl_report_supported_tmf(struct ctl_scsiio *ctsio) data->byte1 |= RST_ATS | RST_ATSS | RST_CTSS | RST_LURS | RST_TRS; data->byte2 |= RST_ITNRS; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -7624,9 +7593,9 @@ ctl_report_timestamp(struct ctl_scsiio *ctsio) scsi_ulto4b(timestamp >> 16, data->timestamp); scsi_ulto2b(timestamp & 0xffff, &data->timestamp[4]); + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -7891,17 +7860,10 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio) } mtx_unlock(&lun->lun_lock); + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - - CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n", - ctsio->kern_data_ptr[0], ctsio->kern_data_ptr[1], - ctsio->kern_data_ptr[2], ctsio->kern_data_ptr[3], - ctsio->kern_data_ptr[4], ctsio->kern_data_ptr[5], - ctsio->kern_data_ptr[6], ctsio->kern_data_ptr[7])); - ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9430,12 +9392,10 @@ ctl_report_luns(struct ctl_scsiio *ctsio) * We can only return SCSI_STATUS_CHECK_COND when we can't satisfy * this request. */ - ctsio->scsi_status = SCSI_STATUS_OK; - + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (retval); } @@ -9549,19 +9509,14 @@ ctl_request_sense(struct ctl_scsiio *ctsio) /* * We report the SCSI status as OK, since the status of the * request sense command itself is OK. - */ - ctsio->scsi_status = SCSI_STATUS_OK; - - /* * We report 0 for the sense length, because we aren't doing * autosense in this case. We're reporting sense as * parameter data. */ - ctsio->sense_len = 0; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9580,17 +9535,14 @@ ctl_request_sense(struct ctl_scsiio *ctsio) /*ascq*/ 0x00, SSD_ELEM_NONE); - ctsio->scsi_status = SCSI_STATUS_OK; - /* * We report 0 for the sense length, because we aren't doing * autosense in this case. We're reporting sense as parameter data. */ - ctsio->sense_len = 0; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9600,9 +9552,7 @@ ctl_tur(struct ctl_scsiio *ctsio) CTL_DEBUG_PRINT(("ctl_tur\n")); - ctsio->scsi_status = SCSI_STATUS_OK; - ctsio->io_hdr.status = CTL_SUCCESS; - + ctl_set_success(ctsio); ctl_done((union ctl_io *)ctsio); return (CTL_RETVAL_COMPLETE); @@ -9677,12 +9627,10 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len) /* Logical Block Provisioning */ pages->page_list[9] = SVPD_LBP; - ctsio->scsi_status = SCSI_STATUS_OK; - + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9733,12 +9681,11 @@ ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len) (char *)lun->be_lun->serial_num, CTL_SN_LEN); } else memset(sn_ptr->serial_num, 0x20, CTL_SN_LEN); - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9784,11 +9731,10 @@ ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len) eid_ptr->flags2 = SVPD_EID_HEADSUP | SVPD_EID_ORDSUP | SVPD_EID_SIMPSUP; eid_ptr->flags3 = SVPD_EID_V_SUP; - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9836,11 +9782,10 @@ ctl_inquiry_evpd_mpp(struct ctl_scsiio *ctsio, int alloc_len) mpp_ptr->descr[0].subpage_code = 0xff; mpp_ptr->descr[0].policy = SVPD_MPP_SHARED; - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -9958,11 +9903,10 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len) memcpy(desc, port->target_devid->data, port->target_devid->len); } - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -10073,11 +10017,10 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len) } mtx_unlock(&softc->ctl_lock); - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -10142,11 +10085,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len) } scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length); - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -10203,11 +10145,10 @@ ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len) bdc_ptr->wab_wac_ff = (i & 0x0f); bdc_ptr->flags = SVPD_FUAB | SVPD_VBULS; - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -10256,11 +10197,10 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len) lbp_ptr->prov_type = SVPD_LBP_THIN; } - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); - return (CTL_RETVAL_COMPLETE); } @@ -10560,7 +10500,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio) } } - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -13531,8 +13471,9 @@ ctl_process_done(union ctl_io *io) * Check to see if we have any errors to inject here. We only * inject errors for commands that don't already have errors set. */ - if ((STAILQ_FIRST(&lun->error_list) != NULL) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) + if ((STAILQ_FIRST(&lun->error_list) != NULL) && + ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) && + ((io->io_hdr.flags & CTL_FLAG_STATUS_SENT) == 0)) ctl_inject_error(lun, io); /* diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index ecaecbdff315..a90245a26e4b 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -381,8 +381,9 @@ ctl_be_block_move_done(union ctl_io *io) * We set status at this point for read commands, and write * commands with errors. */ - if ((io->io_hdr.port_status == 0) && - ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) && + if (io->io_hdr.flags & CTL_FLAG_ABORT) { + ; + } else if ((io->io_hdr.port_status == 0) && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) { lbalen = ARGS(beio->io); if (lbalen->flags & CTL_LLF_READ) { @@ -405,10 +406,9 @@ ctl_be_block_move_done(union ctl_io *io) else ctl_set_success(&io->scsiio); } - } - else if ((io->io_hdr.port_status != 0) - && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) { + } else if ((io->io_hdr.port_status != 0) && + ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE || + (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) { /* * For hardware error sense keys, the sense key * specific value is defined to be a retry count, @@ -532,6 +532,9 @@ ctl_be_block_biodone(struct bio *bio) ctl_set_success(&io->scsiio); ctl_complete_beio(beio); } else { + if ((ARGS(io)->flags & CTL_LLF_READ) && + beio->beio_cont == NULL) + ctl_set_success(&io->scsiio); #ifdef CTL_TIME_IO getbintime(&io->io_hdr.dma_start_bt); #endif @@ -739,6 +742,9 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, ctl_set_success(&io->scsiio); ctl_complete_beio(beio); } else { + if ((ARGS(io)->flags & CTL_LLF_READ) && + beio->beio_cont == NULL) + ctl_set_success(&io->scsiio); #ifdef CTL_TIME_IO getbintime(&io->io_hdr.dma_start_bt); #endif @@ -828,6 +834,9 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun, ctl_set_success(&io->scsiio); ctl_complete_beio(beio); } else { + if ((ARGS(io)->flags & CTL_LLF_READ) && + beio->beio_cont == NULL) + ctl_set_success(&io->scsiio); #ifdef CTL_TIME_IO getbintime(&io->io_hdr.dma_start_bt); #endif diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c index 5f45035148d5..9b3b14ae5945 100644 --- a/sys/cam/ctl/ctl_backend_ramdisk.c +++ b/sys/cam/ctl/ctl_backend_ramdisk.c @@ -238,9 +238,10 @@ ctl_backend_ramdisk_move_done(union ctl_io *io) if (io->scsiio.kern_sg_entries > 0) free(io->scsiio.kern_data_ptr, M_RAMDISK); io->scsiio.kern_rel_offset += io->scsiio.kern_data_len; - if ((io->io_hdr.port_status == 0) - && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) { + if (io->io_hdr.flags & CTL_FLAG_ABORT) { + ; + } else if ((io->io_hdr.port_status == 0) && + ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) { if (io->io_hdr.ctl_private[CTL_PRIV_BACKEND].integer > 0) { mtx_lock(&be_lun->queue_lock); STAILQ_INSERT_TAIL(&be_lun->cont_queue, @@ -250,10 +251,10 @@ ctl_backend_ramdisk_move_done(union ctl_io *io) &be_lun->io_task); return (0); } - io->io_hdr.status = CTL_SUCCESS; - } else if ((io->io_hdr.port_status != 0) - && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) - && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)){ + ctl_set_success(&io->scsiio); + } else if ((io->io_hdr.port_status != 0) && + ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE || + (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) { /* * For hardware error sense keys, the sense key * specific value is defined to be a retry count, diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index a0fdc4104c41..8ec582586b77 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -367,14 +367,16 @@ cfiscsi_pdu_prepare(struct icl_pdu *response) * See the comment below - StatSN is not meaningful and must * not be advanced. */ - if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN) + if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN && + (bhssr->bhssr_flags & BHSDI_FLAGS_S) == 0) advance_statsn = false; /* * 10.7.3: "The fields StatSN, Status, and Residual Count * only have meaningful content if the S bit is set to 1." */ - if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN) + if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN || + (bhssr->bhssr_flags & BHSDI_FLAGS_S)) bhssr->bhssr_statsn = htonl(cs->cs_statsn); bhssr->bhssr_expcmdsn = htonl(cs->cs_cmdsn); bhssr->bhssr_maxcmdsn = htonl(cs->cs_cmdsn + maxcmdsn_delta); @@ -2548,8 +2550,10 @@ cfiscsi_datamove_in(union ctl_io *io) */ buffer_offset += response->ip_data_len; if (buffer_offset == io->scsiio.kern_total_len || - buffer_offset == expected_len) - bhsdi->bhsdi_flags |= BHSDI_FLAGS_F; + buffer_offset == expected_len) { + buffer_offset -= response->ip_data_len; + break; + } cfiscsi_pdu_queue(response); response = NULL; bhsdi = NULL; @@ -2558,8 +2562,27 @@ cfiscsi_datamove_in(union ctl_io *io) if (response != NULL) { buffer_offset += response->ip_data_len; if (buffer_offset == io->scsiio.kern_total_len || - buffer_offset == expected_len) + buffer_offset == expected_len) { bhsdi->bhsdi_flags |= BHSDI_FLAGS_F; + if (io->io_hdr.status == CTL_SUCCESS) { + bhsdi->bhsdi_flags |= BHSDI_FLAGS_S; + if (PDU_TOTAL_TRANSFER_LEN(request) < + ntohl(bhssc->bhssc_expected_data_transfer_length)) { + bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW; + bhsdi->bhsdi_residual_count = + htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) - + PDU_TOTAL_TRANSFER_LEN(request)); + } else if (PDU_TOTAL_TRANSFER_LEN(request) > + ntohl(bhssc->bhssc_expected_data_transfer_length)) { + bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW; + bhsdi->bhsdi_residual_count = + htonl(PDU_TOTAL_TRANSFER_LEN(request) - + ntohl(bhssc->bhssc_expected_data_transfer_length)); + } + bhsdi->bhsdi_status = io->scsiio.scsi_status; + io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; + } + } KASSERT(response->ip_data_len > 0, ("sending empty Data-In")); cfiscsi_pdu_queue(response); } @@ -2765,8 +2788,9 @@ cfiscsi_scsi_command_done(union ctl_io *io) * Do not return status for aborted commands. * There are exceptions, but none supported by CTL yet. */ - if ((io->io_hdr.flags & CTL_FLAG_ABORT) && - (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) { + if (((io->io_hdr.flags & CTL_FLAG_ABORT) && + (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) || + (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) { ctl_free_io(io); icl_pdu_free(request); return; diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h index 643f34fc3fbb..2c2459152d85 100644 --- a/sys/cam/ctl/ctl_io.h +++ b/sys/cam/ctl/ctl_io.h @@ -124,9 +124,10 @@ typedef enum { CTL_FLAG_FAILOVER = 0x04000000, /* Killed by a failover */ CTL_FLAG_IO_ACTIVE = 0x08000000, /* I/O active on this SC */ CTL_FLAG_RDMA_MASK = CTL_FLAG_NO_DATASYNC | CTL_FLAG_BUS_ADDR | - CTL_FLAG_AUTO_MIRROR | CTL_FLAG_REDIR_DONE + CTL_FLAG_AUTO_MIRROR | CTL_FLAG_REDIR_DONE, /* Flags we care about for remote DMA */ + CTL_FLAG_STATUS_SENT = 0x10000000 /* Status sent by datamove */ } ctl_io_flags; diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c index f7648a072ac7..c715f877a0af 100644 --- a/sys/cam/ctl/ctl_tpc.c +++ b/sys/cam/ctl/ctl_tpc.c @@ -425,7 +425,7 @@ ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len) gco_ptr->data_segment_granularity = 0; gco_ptr->inline_data_granularity = 0; - ctsio->scsi_status = SCSI_STATUS_OK; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -487,9 +487,9 @@ ctl_receive_copy_operating_parameters(struct ctl_scsiio *ctsio) data->list_of_implemented_descriptor_type_codes[2] = EC_SEG_REGISTER_KEY; data->list_of_implemented_descriptor_type_codes[3] = EC_CSCD_ID; + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -584,9 +584,9 @@ ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio) scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count); } + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -656,9 +656,9 @@ ctl_receive_copy_failure_details(struct ctl_scsiio *ctsio) scsi_ulto2b(list_copy.sense_len, data->sense_data_length); memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len); + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -742,9 +742,9 @@ ctl_receive_copy_status_lid4(struct ctl_scsiio *ctsio) data->sense_data_length = list_copy.sense_len; memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len); + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -1482,8 +1482,6 @@ tpc_done(union ctl_io *io) * more sophisticated initiator type behavior, the CAM error * recovery code in ../common might be helpful. */ -// if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) -// ctl_io_error_print(io, NULL); tio = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; if (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) && (io->io_hdr.retries > 0)) { @@ -2168,9 +2166,9 @@ ctl_receive_rod_token_information(struct ctl_scsiio *ctsio) printf("RRTI(list=%u) valid=%d\n", scsi_4btoul(cdb->list_identifier), list_copy.res_token_valid); */ + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } @@ -2234,9 +2232,9 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio) /* printf("RART tokens=%d\n", i); */ + ctl_set_success(ctsio); ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; - ctl_datamove((union ctl_io *)ctsio); return (retval); } diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index cbf0cd35e4b5..62aa74485ce0 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -86,7 +86,6 @@ struct ctlfe_softc { STAILQ_HEAD(, ctlfe_softc) ctlfe_softc_list; struct mtx ctlfe_list_mtx; static char ctlfe_mtx_desc[] = "ctlfelist"; -static int ctlfe_dma_enabled = 1; #ifdef CTLFE_INIT_ENABLE static int ctlfe_max_targets = 1; static int ctlfe_num_targets = 0; @@ -101,7 +100,6 @@ struct ctlfe_lun_softc { struct ctlfe_softc *parent_softc; struct cam_periph *periph; ctlfe_lun_flags flags; - struct callout dma_callout; uint64_t ccbs_alloced; uint64_t ccbs_freed; uint64_t ctios_sent; @@ -136,6 +134,7 @@ struct ctlfe_lun_cmd_info { #define CTLFE_MAX_SEGS 32 bus_dma_segment_t cam_sglist[CTLFE_MAX_SEGS]; }; +CTASSERT(sizeof(struct ctlfe_lun_cmd_info) <= CTL_PORT_PRIV_SIZE); /* * When we register the adapter/bus, request that this many ctl_ios be @@ -181,8 +180,6 @@ struct ctlfe_lun_cmd_info { #define RANDOM_WWNN #endif -SYSCTL_INT(_kern_cam_ctl, OID_AUTO, dma_enabled, CTLFLAG_RW, - &ctlfe_dma_enabled, 0, "DMA enabled"); MALLOC_DEFINE(M_CTLFE, "CAM CTL FE", "CAM CTL FE interface"); #define io_ptr ppriv_ptr0 @@ -211,8 +208,8 @@ static int ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id); static void ctlfe_dump_sim(struct cam_sim *sim); static void ctlfe_dump_queue(struct ctlfe_lun_softc *softc); -static void ctlfe_dma_timeout(void *arg); -static void ctlfe_datamove_done(union ctl_io *io); +static void ctlfe_datamove(union ctl_io *io); +static void ctlfe_done(union ctl_io *io); static void ctlfe_dump(void); static struct periph_driver ctlfe_driver = @@ -402,8 +399,8 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) port->lun_enable = ctlfe_lun_enable; port->lun_disable = ctlfe_lun_disable; port->targ_lun_arg = softc; - port->fe_datamove = ctlfe_datamove_done; - port->fe_done = ctlfe_datamove_done; + port->fe_datamove = ctlfe_datamove; + port->fe_done = ctlfe_done; /* * XXX KDM the path inquiry doesn't give us the maximum * number of targets supported. @@ -518,9 +515,6 @@ ctlferegister(struct cam_periph *periph, void *arg) TAILQ_INIT(&softc->work_queue); softc->periph = periph; - - callout_init_mtx(&softc->dma_callout, xpt_path_mtx(periph->path), - /*flags*/ 0); periph->softc = softc; xpt_setup_ccb(&en_lun_ccb.ccb_h, periph->path, CAM_PRIORITY_NONE); @@ -679,8 +673,6 @@ ctlfecleanup(struct cam_periph *periph) * XXX KDM is there anything else that needs to be done here? */ - callout_stop(&softc->dma_callout); - free(softc, M_CTLFE); } @@ -772,260 +764,220 @@ static void ctlfestart(struct cam_periph *periph, union ccb *start_ccb) { struct ctlfe_lun_softc *softc; + struct ctlfe_lun_cmd_info *cmd_info; struct ccb_hdr *ccb_h; + struct ccb_accept_tio *atio; + struct ccb_scsiio *csio; + uint8_t *data_ptr; + uint32_t dxfer_len; + ccb_flags flags; + union ctl_io *io; + uint8_t scsi_status; softc = (struct ctlfe_lun_softc *)periph->softc; - softc->ccbs_alloced++; ccb_h = TAILQ_FIRST(&softc->work_queue); if (ccb_h == NULL) { softc->ccbs_freed++; xpt_release_ccb(start_ccb); - } else { - struct ccb_accept_tio *atio; - struct ccb_scsiio *csio; - uint8_t *data_ptr; - uint32_t dxfer_len; - ccb_flags flags; - union ctl_io *io; - uint8_t scsi_status; - - /* Take the ATIO off the work queue */ - TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe); - atio = (struct ccb_accept_tio *)ccb_h; - io = (union ctl_io *)ccb_h->io_ptr; - csio = &start_ccb->csio; - - flags = atio->ccb_h.flags & - (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); - - if ((io == NULL) - || (io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) { - /* - * We're done, send status back. - */ - flags |= CAM_SEND_STATUS; - if (io == NULL) { - scsi_status = SCSI_STATUS_BUSY; - csio->sense_len = 0; - } else if ((io->io_hdr.flags & CTL_FLAG_ABORT) && - (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) { - io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; - - /* - * If this command was aborted, we don't - * need to send status back to the SIM. - * Just free the CTIO and ctl_io, and - * recycle the ATIO back to the SIM. - */ - xpt_print(periph->path, "%s: aborted " - "command 0x%04x discarded\n", - __func__, io->scsiio.tag_num); - /* - * For a wildcard attachment, commands can - * come in with a specific target/lun. Reset - * the target and LUN fields back to the - * wildcard values before we send them back - * down to the SIM. The SIM has a wildcard - * LUN enabled, not whatever target/lun - * these happened to be. - */ - if (softc->flags & CTLFE_LUN_WILDCARD) { - atio->ccb_h.target_id = - CAM_TARGET_WILDCARD; - atio->ccb_h.target_lun = - CAM_LUN_WILDCARD; - } - - if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { - cam_release_devq(periph->path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); - atio->ccb_h.status &= ~CAM_DEV_QFRZN; - } - - ccb_h = TAILQ_FIRST(&softc->work_queue); - - if (atio->ccb_h.func_code != - XPT_ACCEPT_TARGET_IO) { - xpt_print(periph->path, "%s: func_code " - "is %#x\n", __func__, - atio->ccb_h.func_code); - } - start_ccb->ccb_h.func_code = XPT_ABORT; - start_ccb->cab.abort_ccb = (union ccb *)atio; - - /* Tell the SIM that we've aborted this ATIO */ - xpt_action(start_ccb); - softc->ccbs_freed++; - xpt_release_ccb(start_ccb); - - /* - * Send the ATIO back down to the SIM. - */ - xpt_action((union ccb *)atio); - softc->atios_sent++; - - /* - * If we still have work to do, ask for - * another CCB. Otherwise, deactivate our - * callout. - */ - if (ccb_h != NULL) - xpt_schedule(periph, /*priority*/ 1); - else - callout_stop(&softc->dma_callout); - - return; - } else { - io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; - scsi_status = io->scsiio.scsi_status; - csio->sense_len = io->scsiio.sense_len; - } - data_ptr = NULL; - dxfer_len = 0; - if (io == NULL) { - printf("%s: tag %04x io is NULL\n", __func__, - atio->tag_id); - } else { -#ifdef CTLFEDEBUG - printf("%s: tag %04x status %x\n", __func__, - atio->tag_id, io->io_hdr.status); -#endif - } - csio->sglist_cnt = 0; - if (csio->sense_len != 0) { - csio->sense_data = io->scsiio.sense_data; - flags |= CAM_SEND_SENSE; - } else if (scsi_status == SCSI_STATUS_CHECK_COND) { - xpt_print(periph->path, "%s: check condition " - "with no sense\n", __func__); - } - } else { - struct ctlfe_lun_cmd_info *cmd_info; - - /* - * Datamove call, we need to setup the S/G list. - */ - - cmd_info = (struct ctlfe_lun_cmd_info *) - io->io_hdr.port_priv; - - KASSERT(sizeof(*cmd_info) < CTL_PORT_PRIV_SIZE, - ("%s: sizeof(struct ctlfe_lun_cmd_info) %zd < " - "CTL_PORT_PRIV_SIZE %d", __func__, - sizeof(*cmd_info), CTL_PORT_PRIV_SIZE)); - io->io_hdr.flags &= ~CTL_FLAG_DMA_QUEUED; - - /* - * Need to zero this, in case it has been used for - * a previous datamove for this particular I/O. - */ - bzero(cmd_info, sizeof(*cmd_info)); - scsi_status = 0; - - csio->cdb_len = atio->cdb_len; - - ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len, - &csio->sglist_cnt); - - io->scsiio.ext_data_filled += dxfer_len; - - if (io->scsiio.ext_data_filled > - io->scsiio.kern_total_len) { - xpt_print(periph->path, "%s: tag 0x%04x " - "fill len %u > total %u\n", - __func__, io->scsiio.tag_num, - io->scsiio.ext_data_filled, - io->scsiio.kern_total_len); - } - } - -#ifdef CTLFEDEBUG - printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__, - (flags & CAM_SEND_STATUS) ? "done" : "datamove", - atio->tag_id, flags, data_ptr, dxfer_len); -#endif - - /* - * Valid combinations: - * - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0, - * sglist_cnt = 0 - * - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0, - * sglist_cnt = 0 - * - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0, - * sglist_cnt != 0 - */ -#ifdef CTLFEDEBUG - if (((flags & CAM_SEND_STATUS) - && (((flags & CAM_DATA_SG) != 0) - || (dxfer_len != 0) - || (csio->sglist_cnt != 0))) - || (((flags & CAM_SEND_STATUS) == 0) - && (dxfer_len == 0)) - || ((flags & CAM_DATA_SG) - && (csio->sglist_cnt == 0)) - || (((flags & CAM_DATA_SG) == 0) - && (csio->sglist_cnt != 0))) { - printf("%s: tag %04x cdb %02x flags %#x dxfer_len " - "%d sg %u\n", __func__, atio->tag_id, - atio->cdb_io.cdb_bytes[0], flags, dxfer_len, - csio->sglist_cnt); - if (io != NULL) { - printf("%s: tag %04x io status %#x\n", __func__, - atio->tag_id, io->io_hdr.status); - } else { - printf("%s: tag %04x no associated io\n", - __func__, atio->tag_id); - } - } -#endif - cam_fill_ctio(csio, - /*retries*/ 2, - ctlfedone, - flags, - (flags & CAM_TAG_ACTION_VALID) ? - MSG_SIMPLE_Q_TAG : 0, - atio->tag_id, - atio->init_id, - scsi_status, - /*data_ptr*/ data_ptr, - /*dxfer_len*/ dxfer_len, - /*timeout*/ 5 * 1000); - start_ccb->ccb_h.flags |= CAM_UNLOCKED; - start_ccb->ccb_h.ccb_atio = atio; - if (((flags & CAM_SEND_STATUS) == 0) - && (io != NULL)) - io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; - - softc->ctios_sent++; - - cam_periph_unlock(periph); - xpt_action(start_ccb); - cam_periph_lock(periph); - - if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { - cam_release_devq(periph->path, - /*relsim_flags*/0, - /*reduction*/0, - /*timeout*/0, - /*getcount_only*/0); - atio->ccb_h.status &= ~CAM_DEV_QFRZN; - } - - ccb_h = TAILQ_FIRST(&softc->work_queue); + return; } + + /* Take the ATIO off the work queue */ + TAILQ_REMOVE(&softc->work_queue, ccb_h, periph_links.tqe); + atio = (struct ccb_accept_tio *)ccb_h; + io = (union ctl_io *)ccb_h->io_ptr; + csio = &start_ccb->csio; + + flags = atio->ccb_h.flags & + (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); + cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv; + cmd_info->cur_transfer_index = 0; + cmd_info->cur_transfer_off = 0; + cmd_info->flags = 0; + + if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) { + /* + * Datamove call, we need to setup the S/G list. + */ + scsi_status = 0; + csio->cdb_len = atio->cdb_len; + ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len, + &csio->sglist_cnt); + io->scsiio.ext_data_filled += dxfer_len; + if (io->scsiio.ext_data_filled > io->scsiio.kern_total_len) { + xpt_print(periph->path, "%s: tag 0x%04x " + "fill len %u > total %u\n", + __func__, io->scsiio.tag_num, + io->scsiio.ext_data_filled, + io->scsiio.kern_total_len); + } + } else { + /* + * We're done, send status back. + */ + if ((io->io_hdr.flags & CTL_FLAG_ABORT) && + (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) { + io->io_hdr.flags &= ~CTL_FLAG_STATUS_QUEUED; + + /* + * If this command was aborted, we don't + * need to send status back to the SIM. + * Just free the CTIO and ctl_io, and + * recycle the ATIO back to the SIM. + */ + xpt_print(periph->path, "%s: aborted " + "command 0x%04x discarded\n", + __func__, io->scsiio.tag_num); + /* + * For a wildcard attachment, commands can + * come in with a specific target/lun. Reset + * the target and LUN fields back to the + * wildcard values before we send them back + * down to the SIM. The SIM has a wildcard + * LUN enabled, not whatever target/lun + * these happened to be. + */ + if (softc->flags & CTLFE_LUN_WILDCARD) { + atio->ccb_h.target_id = CAM_TARGET_WILDCARD; + atio->ccb_h.target_lun = CAM_LUN_WILDCARD; + } + + if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(periph->path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + atio->ccb_h.status &= ~CAM_DEV_QFRZN; + } + + if (atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) { + xpt_print(periph->path, "%s: func_code " + "is %#x\n", __func__, + atio->ccb_h.func_code); + } + start_ccb->ccb_h.func_code = XPT_ABORT; + start_ccb->cab.abort_ccb = (union ccb *)atio; + + /* Tell the SIM that we've aborted this ATIO */ + xpt_action(start_ccb); + softc->ccbs_freed++; + xpt_release_ccb(start_ccb); + + /* + * Send the ATIO back down to the SIM. + */ + xpt_action((union ccb *)atio); + softc->atios_sent++; + + /* + * If we still have work to do, ask for + * another CCB. Otherwise, deactivate our + * callout. + */ + if (!TAILQ_EMPTY(&softc->work_queue)) + xpt_schedule(periph, /*priority*/ 1); + return; + } + data_ptr = NULL; + dxfer_len = 0; + csio->sglist_cnt = 0; + scsi_status = 0; + } + if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) && + (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 && + ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 || + io->io_hdr.status == CTL_SUCCESS)) { + io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; + flags |= CAM_SEND_STATUS; + scsi_status = io->scsiio.scsi_status; + csio->sense_len = io->scsiio.sense_len; +#ifdef CTLFEDEBUG + printf("%s: tag %04x status %x\n", __func__, + atio->tag_id, io->io_hdr.status); +#endif + if (csio->sense_len != 0) { + csio->sense_data = io->scsiio.sense_data; + flags |= CAM_SEND_SENSE; + } else if (scsi_status == SCSI_STATUS_CHECK_COND) { + xpt_print(periph->path, "%s: check condition " + "with no sense\n", __func__); + } + } + +#ifdef CTLFEDEBUG + printf("%s: %s: tag %04x flags %x ptr %p len %u\n", __func__, + (flags & CAM_SEND_STATUS) ? "done" : "datamove", + atio->tag_id, flags, data_ptr, dxfer_len); +#endif + /* - * If we still have work to do, ask for another CCB. Otherwise, - * deactivate our callout. + * Valid combinations: + * - CAM_SEND_STATUS, CAM_DATA_SG = 0, dxfer_len = 0, + * sglist_cnt = 0 + * - CAM_SEND_STATUS = 0, CAM_DATA_SG = 0, dxfer_len != 0, + * sglist_cnt = 0 + * - CAM_SEND_STATUS = 0, CAM_DATA_SG, dxfer_len != 0, + * sglist_cnt != 0 */ - if (ccb_h != NULL) +#ifdef CTLFEDEBUG + if (((flags & CAM_SEND_STATUS) + && (((flags & CAM_DATA_SG) != 0) + || (dxfer_len != 0) + || (csio->sglist_cnt != 0))) + || (((flags & CAM_SEND_STATUS) == 0) + && (dxfer_len == 0)) + || ((flags & CAM_DATA_SG) + && (csio->sglist_cnt == 0)) + || (((flags & CAM_DATA_SG) == 0) + && (csio->sglist_cnt != 0))) { + printf("%s: tag %04x cdb %02x flags %#x dxfer_len " + "%d sg %u\n", __func__, atio->tag_id, + atio->cdb_io.cdb_bytes[0], flags, dxfer_len, + csio->sglist_cnt); + printf("%s: tag %04x io status %#x\n", __func__, + atio->tag_id, io->io_hdr.status); + } +#endif + cam_fill_ctio(csio, + /*retries*/ 2, + ctlfedone, + flags, + (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0, + atio->tag_id, + atio->init_id, + scsi_status, + /*data_ptr*/ data_ptr, + /*dxfer_len*/ dxfer_len, + /*timeout*/ 5 * 1000); + start_ccb->ccb_h.flags |= CAM_UNLOCKED; + start_ccb->ccb_h.ccb_atio = atio; + if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) + io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; + io->io_hdr.flags &= ~(CTL_FLAG_DMA_QUEUED | CTL_FLAG_STATUS_QUEUED); + + softc->ctios_sent++; + + cam_periph_unlock(periph); + xpt_action(start_ccb); + cam_periph_lock(periph); + + if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(periph->path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + atio->ccb_h.status &= ~CAM_DEV_QFRZN; + } + + /* + * If we still have work to do, ask for another CCB. + */ + if (!TAILQ_EMPTY(&softc->work_queue)) xpt_schedule(periph, /*priority*/ 1); - else - callout_stop(&softc->dma_callout); } static void @@ -1278,7 +1230,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) | (done_ccb->csio.msg_ptr[6]); } - if (srr && (done_ccb->ccb_h.flags & CAM_SEND_STATUS)) { + if (srr && (io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) { /* * If status was being sent, the back end data is now * history. Hack it up and resubmit a new command with @@ -1317,7 +1269,7 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb) * resources. If we were doing a datamove, call the * datamove done routine. */ - if (done_ccb->ccb_h.flags & CAM_SEND_STATUS) { + if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) { softc->ccbs_freed++; xpt_release_ccb(done_ccb); /* @@ -1986,7 +1938,6 @@ ctlfe_dump_sim(struct cam_sim *sim) printf("%s%d: max tagged openings: %d, max dev openings: %d\n", sim->sim_name, sim->unit_number, sim->max_tagged_dev_openings, sim->max_dev_openings); - printf("\n"); } /* @@ -2003,26 +1954,10 @@ ctlfe_dump_queue(struct ctlfe_lun_softc *softc) num_items = 0; TAILQ_FOREACH(hdr, &softc->work_queue, periph_links.tqe) { - union ctl_io *io; - - io = hdr->io_ptr; + union ctl_io *io = hdr->io_ptr; num_items++; - /* - * This can happen when we get an ATIO but can't allocate - * a ctl_io. See the XPT_ACCEPT_TARGET_IO case in ctlfedone(). - */ - if (io == NULL) { - struct ccb_scsiio *csio; - - csio = (struct ccb_scsiio *)hdr; - - xpt_print(periph->path, "CCB %#x ctl_io allocation " - "failed\n", csio->tag_id); - continue; - } - /* * Only regular SCSI I/O is put on the work * queue, so we can print sense here. There may be no @@ -2035,20 +1970,15 @@ ctlfe_dump_queue(struct ctlfe_lun_softc *softc) ctl_io_error_print(io, NULL); /* - * We're sending status back to the - * initiator, so we're on the queue waiting - * for a CTIO to do that. + * Print DMA status if we are DMA_QUEUED. */ - if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) - continue; - - /* - * Otherwise, we're on the queue waiting to - * do a data transfer. - */ - xpt_print(periph->path, "Total %u, Current %u, Resid %u\n", - io->scsiio.kern_total_len, io->scsiio.kern_data_len, - io->scsiio.kern_data_resid); + if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) { + xpt_print(periph->path, + "Total %u, Current %u, Resid %u\n", + io->scsiio.kern_total_len, + io->scsiio.kern_data_len, + io->scsiio.kern_data_resid); + } } xpt_print(periph->path, "%d requests total waiting for CCBs\n", @@ -2063,67 +1993,44 @@ ctlfe_dump_queue(struct ctlfe_lun_softc *softc) softc->ctios_returned); } -/* - * This function is called when we fail to get a CCB for a DMA or status return - * to the initiator within the specified time period. - * - * The callout code should insure that we hold the sim mutex here. - */ -static void -ctlfe_dma_timeout(void *arg) -{ - struct ctlfe_lun_softc *softc; - struct cam_periph *periph; - struct cam_sim *sim; - int num_queued; - - softc = (struct ctlfe_lun_softc *)arg; - periph = softc->periph; - sim = xpt_path_sim(periph->path); - num_queued = 0; - - /* - * Nothing to do... - */ - if (TAILQ_FIRST(&softc->work_queue) == NULL) { - xpt_print(periph->path, "TIMEOUT triggered after %d " - "seconds, but nothing on work queue??\n", - CTLFE_DMA_TIMEOUT); - return; - } - - xpt_print(periph->path, "TIMEOUT (%d seconds) waiting for DMA to " - "start\n", CTLFE_DMA_TIMEOUT); - - ctlfe_dump_queue(softc); - - ctlfe_dump_sim(sim); - - xpt_print(periph->path, "calling xpt_schedule() to attempt to " - "unstick our queue\n"); - - xpt_schedule(periph, /*priority*/ 1); - - xpt_print(periph->path, "xpt_schedule() call complete\n"); -} - /* * Datamove/done routine called by CTL. Put ourselves on the queue to * receive a CCB from CAM so we can queue the continue I/O request down * to the adapter. */ static void -ctlfe_datamove_done(union ctl_io *io) +ctlfe_datamove(union ctl_io *io) +{ + union ccb *ccb; + struct cam_periph *periph; + struct ctlfe_lun_softc *softc; + + KASSERT(io->io_hdr.io_type == CTL_IO_SCSI, + ("Unexpected io_type (%d) in ctlfe_datamove", io->io_hdr.io_type)); + + ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; + periph = xpt_path_periph(ccb->ccb_h.path); + cam_periph_lock(periph); + softc = (struct ctlfe_lun_softc *)periph->softc; + io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED; + if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) + io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; + TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, + periph_links.tqe); + xpt_schedule(periph, /*priority*/ 1); + cam_periph_unlock(periph); +} + +static void +ctlfe_done(union ctl_io *io) { union ccb *ccb; struct cam_periph *periph; struct ctlfe_lun_softc *softc; ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; - periph = xpt_path_periph(ccb->ccb_h.path); cam_periph_lock(periph); - softc = (struct ctlfe_lun_softc *)periph->softc; if (io->io_hdr.io_type == CTL_IO_TASK) { @@ -2142,28 +2049,24 @@ ctlfe_datamove_done(union ctl_io *io) ccb->ccb_h.status = CAM_REQ_INPROG; ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE; xpt_action(ccb); + } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) { + if (softc->flags & CTLFE_LUN_WILDCARD) { + ccb->ccb_h.target_id = CAM_TARGET_WILDCARD; + ccb->ccb_h.target_lun = CAM_LUN_WILDCARD; + } + if (periph->flags & CAM_PERIPH_INVALID) { + ctlfe_free_ccb(periph, ccb); + } else { + softc->atios_sent++; + cam_periph_unlock(periph); + xpt_action(ccb); + return; + } } else { - if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE) - io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; - else - io->io_hdr.flags |= CTL_FLAG_DMA_QUEUED; - + io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED; TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, periph_links.tqe); - - /* - * Reset the timeout for our latest active DMA. - */ - callout_reset(&softc->dma_callout, - CTLFE_DMA_TIMEOUT * hz, - ctlfe_dma_timeout, softc); - /* - * Ask for the CAM transport layer to send us a CCB to do - * the DMA or send status, unless ctlfe_dma_enabled is set - * to 0. - */ - if (ctlfe_dma_enabled != 0) - xpt_schedule(periph, /*priority*/ 1); + xpt_schedule(periph, /*priority*/ 1); } cam_periph_unlock(periph); @@ -2173,14 +2076,11 @@ static void ctlfe_dump(void) { struct ctlfe_softc *bus_softc; + struct ctlfe_lun_softc *lun_softc; STAILQ_FOREACH(bus_softc, &ctlfe_softc_list, links) { - struct ctlfe_lun_softc *lun_softc; - ctlfe_dump_sim(bus_softc->sim); - - STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links) { + STAILQ_FOREACH(lun_softc, &bus_softc->lun_softc_list, links) ctlfe_dump_queue(lun_softc); - } } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 3a455d73899c..472afe0172c2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -5274,7 +5274,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize); ARCSTAT_INCR(arcstat_l2_size, write_sz); ARCSTAT_INCR(arcstat_l2_asize, write_asize); - vdev_space_update(dev->l2ad_vdev, write_psize, 0, 0); + vdev_space_update(dev->l2ad_vdev, write_asize, 0, 0); /* * Bump device hand to the device start if it is approaching the end. diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 4433e186afa6..93dd80db0640 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -690,9 +690,9 @@ linux_times(struct thread *td, struct linux_times_args *args) if (args->buf != NULL) { p = td->td_proc; PROC_LOCK(p); - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &utime, &stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); calccru(p, &cutime, &cstime); PROC_UNLOCK(p); diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 9e9b020a832f..cef1b488e673 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -864,9 +864,9 @@ svr4_sys_times(td, uap) p = td->td_proc; PROC_LOCK(p); - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &utime, &stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); calccru(p, &cutime, &cstime); PROC_UNLOCK(p); @@ -1277,9 +1277,9 @@ svr4_sys_waitsys(td, uap) pid = p->p_pid; status = p->p_xstat; ru = p->p_ru; - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &ru.ru_utime, &ru.ru_stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); PROC_UNLOCK(p); sx_sunlock(&proctree_lock); @@ -1304,9 +1304,9 @@ svr4_sys_waitsys(td, uap) pid = p->p_pid; status = W_STOPCODE(p->p_xstat); ru = p->p_ru; - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &ru.ru_utime, &ru.ru_stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); PROC_UNLOCK(p); if (((uap->options & SVR4_WNOWAIT)) == 0) { @@ -1328,9 +1328,9 @@ svr4_sys_waitsys(td, uap) pid = p->p_pid; ru = p->p_ru; status = SIGCONT; - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &ru.ru_utime, &ru.ru_stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); PROC_UNLOCK(p); if (((uap->options & SVR4_WNOWAIT)) == 0) { diff --git a/sys/conf/files b/sys/conf/files index 77a619d4b920..f83785884242 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -660,6 +660,8 @@ dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard +dev/altera/pio/pio.c optional altera_pio +dev/altera/pio/pio_if.m optional altera_pio dev/amdpm/amdpm.c optional amdpm pci | nfpm pci dev/amdsmb/amdsmb.c optional amdsmb pci dev/amr/amr.c optional amr @@ -2570,6 +2572,19 @@ dev/utopia/suni.c optional utopia dev/utopia/utopia.c optional utopia dev/vge/if_vge.c optional vge dev/viapm/viapm.c optional viapm pci +dev/virtio/virtio.c optional virtio +dev/virtio/virtqueue.c optional virtio +dev/virtio/virtio_bus_if.m optional virtio +dev/virtio/virtio_if.m optional virtio +dev/virtio/pci/virtio_pci.c optional virtio_pci +dev/virtio/mmio/virtio_mmio.c optional virtio_mmio +dev/virtio/mmio/virtio_mmio_if.m optional virtio_mmio +dev/virtio/network/if_vtnet.c optional vtnet +dev/virtio/block/virtio_blk.c optional virtio_blk +dev/virtio/balloon/virtio_balloon.c optional virtio_balloon +dev/virtio/scsi/virtio_scsi.c optional virtio_scsi +dev/virtio/random/virtio_random.c optional virtio_random +dev/virtio/console/virtio_console.c optional virtio_console dev/vkbd/vkbd.c optional vkbd dev/vr/if_vr.c optional vr pci dev/vt/colors/vt_termcolors.c optional vt diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index c53222777c85..d8a3a632a5e2 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -445,17 +445,6 @@ dev/isci/scil/scif_sas_task_request.c optional isci dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci dev/isci/scil/scif_sas_task_request_states.c optional isci dev/isci/scil/scif_sas_timer.c optional isci -dev/virtio/virtio.c optional virtio -dev/virtio/virtqueue.c optional virtio -dev/virtio/virtio_bus_if.m optional virtio -dev/virtio/virtio_if.m optional virtio -dev/virtio/pci/virtio_pci.c optional virtio_pci -dev/virtio/network/if_vtnet.c optional vtnet -dev/virtio/block/virtio_blk.c optional virtio_blk -dev/virtio/balloon/virtio_balloon.c optional virtio_balloon -dev/virtio/scsi/virtio_scsi.c optional virtio_scsi -dev/virtio/random/virtio_random.c optional virtio_random -dev/virtio/console/virtio_console.c optional virtio_console isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/kern_clocksource.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 6ebf0da52cbc..86919861e8b0 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -392,17 +392,6 @@ dev/isci/scil/scif_sas_task_request.c optional isci dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci dev/isci/scil/scif_sas_task_request_states.c optional isci dev/isci/scil/scif_sas_timer.c optional isci -dev/virtio/virtio.c optional virtio -dev/virtio/virtqueue.c optional virtio -dev/virtio/virtio_bus_if.m optional virtio -dev/virtio/virtio_if.m optional virtio -dev/virtio/pci/virtio_pci.c optional virtio_pci -dev/virtio/network/if_vtnet.c optional vtnet -dev/virtio/block/virtio_blk.c optional virtio_blk -dev/virtio/balloon/virtio_balloon.c optional virtio_balloon -dev/virtio/scsi/virtio_scsi.c optional virtio_scsi -dev/virtio/random/virtio_random.c optional virtio_random -dev/virtio/console/virtio_console.c optional virtio_console i386/acpica/acpi_machdep.c optional acpi acpi_wakecode.o optional acpi \ dependency "$S/i386/acpica/acpi_wakecode.S assym.s" \ diff --git a/sys/contrib/dev/ral/Makefile b/sys/contrib/dev/ral/Makefile index 0e74d3ab55a5..6ef8a9a535a9 100644 --- a/sys/contrib/dev/ral/Makefile +++ b/sys/contrib/dev/ral/Makefile @@ -3,7 +3,8 @@ FILES= rt2561s.fw.uu rt2561.fw.uu rt2661.fw.uu rt2860.fw.uu rt2561s.fw.uu: microcode.h LICENSE - (echo '#include '; \ + (echo '#include '; \ + echo '#include '; \ cat microcode.h; \ echo 'int main(void) { \ write(1, rt2561s, sizeof(rt2561s)); return 0; \ @@ -11,7 +12,8 @@ rt2561s.fw.uu: microcode.h LICENSE (sed 's/^/# /' LICENSE; ./build | uuencode rt2561s.fw) > ${.TARGET} rt2561.fw.uu: microcode.h LICENSE - (echo '#include '; \ + (echo '#include '; \ + echo '#include '; \ cat microcode.h; \ echo 'int main(void) { \ write(1, rt2561, sizeof(rt2561)); return 0; \ @@ -19,7 +21,8 @@ rt2561.fw.uu: microcode.h LICENSE (sed 's/^/# /' LICENSE; ./build | uuencode rt2561.fw) > ${.TARGET} rt2661.fw.uu: microcode.h LICENSE - (echo '#include '; \ + (echo '#include '; \ + echo '#include '; \ cat microcode.h; \ echo 'int main(void) { \ write(1, rt2661, sizeof(rt2661)); return 0; \ @@ -27,7 +30,8 @@ rt2661.fw.uu: microcode.h LICENSE (sed 's/^/# /' LICENSE; ./build | uuencode rt2661.fw) > ${.TARGET} rt2860.fw.uu: microcode.h LICENSE - (echo '#include '; \ + (echo '#include '; \ + echo '#include '; \ cat microcode.h; \ echo 'int main(void) { \ write(1, rt2860, sizeof(rt2860)); return 0; \ diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 4d86e47d9fb6..55a2a4d76d49 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -252,7 +252,7 @@ static const struct optlist ipopts[20] = { }; #ifdef USE_INET6 -static struct optlist ip6exthdr[] = { +static const struct optlist ip6exthdr[] = { { IPPROTO_HOPOPTS, 0x000001 }, { IPPROTO_IPV6, 0x000002 }, { IPPROTO_ROUTING, 0x000004 }, diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 831326c2978a..7e3457a91b79 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -112,7 +112,7 @@ static void ipf_frag_free __P((ipf_frag_softc_t *, ipfr_t *)); static frentry_t ipfr_block; -ipftuneable_t ipf_tuneables[] = { +const ipftuneable_t ipf_tuneables[] = { { { (void *)offsetof(ipf_frag_softc_t, ipfr_size) }, "frag_size", 1, 0x7fffffff, stsizeof(ipf_frag_softc_t, ipfr_size), diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c index 7b05d8406f63..305f6b070679 100644 --- a/sys/dev/ahci/ahci_pci.c +++ b/sys/dev/ahci/ahci_pci.c @@ -148,6 +148,14 @@ static struct { {0x8c078086, 0x00, "Intel Lynx Point (RAID)", 0}, {0x8c0e8086, 0x00, "Intel Lynx Point (RAID)", 0}, {0x8c0f8086, 0x00, "Intel Lynx Point (RAID)", 0}, + {0x8c828086, 0x00, "Intel Wildcat Point", 0}, + {0x8c838086, 0x00, "Intel Wildcat Point", 0}, + {0x8c848086, 0x00, "Intel Wildcat Point (RAID)", 0}, + {0x8c858086, 0x00, "Intel Wildcat Point (RAID)", 0}, + {0x8c868086, 0x00, "Intel Wildcat Point (RAID)", 0}, + {0x8c878086, 0x00, "Intel Wildcat Point (RAID)", 0}, + {0x8c8e8086, 0x00, "Intel Wildcat Point (RAID)", 0}, + {0x8c8f8086, 0x00, "Intel Wildcat Point (RAID)", 0}, {0x8d028086, 0x00, "Intel Wellsburg", 0}, {0x8d048086, 0x00, "Intel Wellsburg (RAID)", 0}, {0x8d068086, 0x00, "Intel Wellsburg (RAID)", 0}, diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index dc1e49412470..c8942d1b8740 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -275,6 +275,19 @@ struct ata_pci_controller { #define ATA_LPT_R5 0x8c0e8086 #define ATA_LPT_R6 0x8c0f8086 +#define ATA_WCPT_S1 0x8c808086 +#define ATA_WCPT_S2 0x8c818086 +#define ATA_WCPT_AH1 0x8c828086 +#define ATA_WCPT_AH2 0x8c838086 +#define ATA_WCPT_R1 0x8c848086 +#define ATA_WCPT_R2 0x8c858086 +#define ATA_WCPT_R3 0x8c868086 +#define ATA_WCPT_R4 0x8c878086 +#define ATA_WCPT_S3 0x8c888086 +#define ATA_WCPT_S4 0x8c898086 +#define ATA_WCPT_R5 0x8c8e8086 +#define ATA_WCPT_R6 0x8c8f8086 + #define ATA_WELLS_S1 0x8d008086 #define ATA_WELLS_S2 0x8d088086 #define ATA_WELLS_S3 0x8d608086 diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index 33078354f1df..c135dd75b979 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -227,6 +227,18 @@ ata_intel_probe(device_t dev) { ATA_LPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Lynx Point" }, { ATA_LPT_R5, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, { ATA_LPT_R6, 0, INTEL_AHCI, 0, ATA_SA300, "Lynx Point" }, + { ATA_WCPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R3, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R4, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R5, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, + { ATA_WCPT_R6, 0, INTEL_AHCI, 0, ATA_SA300, "Wildcat Point" }, { ATA_WELLS_S1, 0, INTEL_6CH, 0, ATA_SA300, "Wellsburg" }, { ATA_WELLS_S2, 0, INTEL_6CH2, 0, ATA_SA300, "Wellsburg" }, { ATA_WELLS_S3, 0, INTEL_6CH, 0, ATA_SA300, "Wellsburg" }, diff --git a/sys/dev/beri/virtio/virtio.c b/sys/dev/beri/virtio/virtio.c new file mode 100644 index 000000000000..5ad4ff9a80d0 --- /dev/null +++ b/sys/dev/beri/virtio/virtio.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 2014 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * BERI virtio mmio backend common methods + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +int +vq_ring_ready(struct vqueue_info *vq) +{ + + return (vq->vq_flags & VQ_ALLOC); +} + +int +vq_has_descs(struct vqueue_info *vq) +{ + + return (vq_ring_ready(vq) && vq->vq_last_avail != + be16toh(vq->vq_avail->idx)); +} + +void * +paddr_map(uint32_t offset, uint32_t phys, uint32_t size) +{ + bus_space_handle_t bsh; + + if (bus_space_map(fdtbus_bs_tag, (phys + offset), + size, 0, &bsh) != 0) { + panic("Couldn't map 0x%08x\n", (phys + offset)); + } + + return (void *)(bsh); +} + +void +paddr_unmap(void *phys, uint32_t size) +{ + + bus_space_unmap(fdtbus_bs_tag, (bus_space_handle_t)phys, size); +} + +static inline void +_vq_record(uint32_t offs, int i, volatile struct vring_desc *vd, + struct iovec *iov, int n_iov, uint16_t *flags) { + + if (i >= n_iov) + return; + + iov[i].iov_base = paddr_map(offs, be64toh(vd->addr), + be32toh(vd->len)); + iov[i].iov_len = be32toh(vd->len); + if (flags != NULL) + flags[i] = be16toh(vd->flags); +} + +int +vq_getchain(uint32_t offs, struct vqueue_info *vq, + struct iovec *iov, int n_iov, uint16_t *flags) +{ + volatile struct vring_desc *vdir, *vindir, *vp; + int idx, ndesc, n_indir; + int head, next; + int i; + + idx = vq->vq_last_avail; + ndesc = (be16toh(vq->vq_avail->idx) - idx); + if (ndesc == 0) + return (0); + + head = be16toh(vq->vq_avail->ring[idx & (vq->vq_qsize - 1)]); + next = head; + + for (i = 0; i < VQ_MAX_DESCRIPTORS; next = be16toh(vdir->next)) { + vdir = &vq->vq_desc[next]; + if ((be16toh(vdir->flags) & VRING_DESC_F_INDIRECT) == 0) { + _vq_record(offs, i, vdir, iov, n_iov, flags); + i++; + } else { + n_indir = be32toh(vdir->len) / 16; + vindir = paddr_map(offs, be64toh(vdir->addr), + be32toh(vdir->len)); + next = 0; + for (;;) { + vp = &vindir[next]; + _vq_record(offs, i, vp, iov, n_iov, flags); + i+=1; + if ((be16toh(vp->flags) & \ + VRING_DESC_F_NEXT) == 0) + break; + next = be16toh(vp->next); + } + paddr_unmap((void *)vindir, be32toh(vdir->len)); + } + + if ((be16toh(vdir->flags) & VRING_DESC_F_NEXT) == 0) + return (i); + } + + return (i); +} + +void +vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen) +{ + volatile struct vring_used_elem *vue; + volatile struct vring_used *vu; + uint16_t head, uidx, mask; + int i; + + mask = vq->vq_qsize - 1; + head = be16toh(vq->vq_avail->ring[vq->vq_last_avail++ & mask]); + + vu = vq->vq_used; + uidx = be16toh(vu->idx); + vue = &vu->ring[uidx++ & mask]; + vue->id = htobe16(head); + vue->len = htobe32(iolen); + vu->idx = htobe16(uidx); + + /* Clean up */ + for (i = 1; i < (n-1); i++) { + paddr_unmap((void *)iov[i].iov_base, iov[i].iov_len); + } +} diff --git a/sys/dev/beri/virtio/virtio.h b/sys/dev/beri/virtio/virtio.h new file mode 100644 index 000000000000..a3461ad72eea --- /dev/null +++ b/sys/dev/beri/virtio/virtio.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2014 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define READ2(_sc, _reg) \ + bus_read_2((_sc)->res[0], _reg) +#define READ4(_sc, _reg) \ + bus_read_4((_sc)->res[0], _reg) +#define WRITE2(_sc, _reg, _val) \ + bus_write_2((_sc)->res[0], _reg, _val) +#define WRITE4(_sc, _reg, _val) \ + bus_write_4((_sc)->res[0], _reg, _val) + +#define PAGE_SHIFT 12 +#define VRING_ALIGN 4096 +#define NUM_QUEUES 1 + +#define VQ_ALLOC 0x01 /* set once we have a pfn */ +#define VQ_MAX_DESCRIPTORS 512 + +#define VTBLK_BLK_ID_BYTES 20 +#define VTBLK_MAXSEGS 256 + +struct vqueue_info { + uint16_t vq_qsize; /* size of this queue (a power of 2) */ + uint16_t vq_num; + uint16_t vq_flags; + uint16_t vq_last_avail; /* a recent value of vq_avail->va_idx */ + uint16_t vq_save_used; /* saved vq_used->vu_idx; see vq_endchains */ + uint32_t vq_pfn; /* PFN of virt queue (not shifted!) */ + + volatile struct vring_desc *vq_desc; /* descriptor array */ + volatile struct vring_avail *vq_avail; /* the "avail" ring */ + volatile struct vring_used *vq_used; /* the "used" ring */ +}; + +int vq_ring_ready(struct vqueue_info *vq); +int vq_has_descs(struct vqueue_info *vq); +void * paddr_map(uint32_t offset, uint32_t phys, uint32_t size); +void paddr_unmap(void *phys, uint32_t size); +int vq_getchain(uint32_t beri_mem_offset, struct vqueue_info *vq, + struct iovec *iov, int n_iov, uint16_t *flags); +void vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen); + diff --git a/sys/dev/beri/virtio/virtio_block.c b/sys/dev/beri/virtio/virtio_block.c new file mode 100644 index 000000000000..d0788542beb2 --- /dev/null +++ b/sys/dev/beri/virtio/virtio_block.c @@ -0,0 +1,602 @@ +/*- + * Copyright (c) 2014 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * BERI virtio block backend driver + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pio_if.h" + +#define DPRINTF(fmt, ...) + +struct beri_vtblk_softc { + struct resource *res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + struct cdev *cdev; + device_t dev; + int opened; + device_t pio_recv; + device_t pio_send; + struct vqueue_info vs_queues[NUM_QUEUES]; + char ident[VTBLK_BLK_ID_BYTES]; + struct ucred *cred; + struct vnode *vnode; + struct thread *vtblk_ktd; + struct sx sc_mtx; + int beri_mem_offset; + struct md_ioctl *mdio; + struct virtio_blk_config *cfg; +}; + +static struct resource_spec beri_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +vtblk_rdwr(struct beri_vtblk_softc *sc, struct iovec *iov, + int cnt, int offset, int operation, int iolen) +{ + struct vnode *vp; + struct mount *mp; + struct uio auio; + int error; + + bzero(&auio, sizeof(auio)); + + vp = sc->vnode; + + KASSERT(vp != NULL, ("file not opened")); + + auio.uio_iov = iov; + auio.uio_iovcnt = cnt; + auio.uio_offset = offset; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = operation; + auio.uio_resid = iolen; + auio.uio_td = curthread; + + if (operation == 0) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_READ(vp, &auio, IO_DIRECT, sc->cred); + VOP_UNLOCK(vp, 0); + } else { + (void) vn_start_write(vp, &mp, V_WAIT); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + error = VOP_WRITE(vp, &auio, IO_SYNC, sc->cred); + VOP_UNLOCK(vp, 0); + vn_finished_write(mp); + } + + return (error); +} + +static void +vtblk_proc(struct beri_vtblk_softc *sc, struct vqueue_info *vq) +{ + struct iovec iov[VTBLK_MAXSEGS + 2]; + uint16_t flags[VTBLK_MAXSEGS + 2]; + struct virtio_blk_outhdr *vbh; + uint8_t *status; + off_t offset; + int iolen; + int type; + int i, n; + int err; + + n = vq_getchain(sc->beri_mem_offset, vq, iov, + VTBLK_MAXSEGS + 2, flags); + + KASSERT(n >= 2 && n <= VTBLK_MAXSEGS + 2, + ("wrong n value %d", n)); + + vbh = iov[0].iov_base; + + status = iov[n-1].iov_base; + KASSERT(iov[n-1].iov_len == 1, + ("iov_len == %d", iov[n-1].iov_len)); + + type = be32toh(vbh->type) & ~VIRTIO_BLK_T_BARRIER; + offset = be64toh(vbh->sector) * DEV_BSIZE; + + iolen = 0; + for (i = 1; i < (n-1); i++) { + iolen += iov[i].iov_len; + } + + switch (type) { + case VIRTIO_BLK_T_OUT: + case VIRTIO_BLK_T_IN: + err = vtblk_rdwr(sc, iov + 1, i - 1, + offset, type, iolen); + break; + case VIRTIO_BLK_T_GET_ID: + /* Assume a single buffer */ + strlcpy(iov[1].iov_base, sc->ident, + MIN(iov[1].iov_len, sizeof(sc->ident))); + err = 0; + break; + case VIRTIO_BLK_T_FLUSH: + /* Possible? */ + default: + err = -ENOSYS; + break; + } + + if (err < 0) { + if (err == -ENOSYS) { + *status = VIRTIO_BLK_S_UNSUPP; + } else + *status = VIRTIO_BLK_S_IOERR; + } else + *status = VIRTIO_BLK_S_OK; + + vq_relchain(vq, iov, n, 1); +} + +static int +close_file(struct beri_vtblk_softc *sc, struct thread *td) +{ + int error; + + if (sc->vnode != NULL) { + vn_lock(sc->vnode, LK_EXCLUSIVE | LK_RETRY); + sc->vnode->v_vflag &= ~VV_MD; + VOP_UNLOCK(sc->vnode, 0); + error = vn_close(sc->vnode, (FREAD|FWRITE), + sc->cred, td); + if (error != 0) + return (error); + sc->vnode = NULL; + } + + if (sc->cred != NULL) + crfree(sc->cred); + + return (0); +} + +static int +open_file(struct beri_vtblk_softc *sc, struct thread *td) +{ + struct nameidata nd; + struct vattr vattr; + int error; + int flags; + + flags = (FREAD | FWRITE); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, + sc->mdio->md_file, td); + error = vn_open(&nd, &flags, 0, NULL); + if (error != 0) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + if (nd.ni_vp->v_type != VREG) { + return (EINVAL); + } + + error = VOP_GETATTR(nd.ni_vp, &vattr, td->td_ucred); + if (error != 0) + return (error); + + if (VOP_ISLOCKED(nd.ni_vp) != LK_EXCLUSIVE) { + vn_lock(nd.ni_vp, LK_UPGRADE | LK_RETRY); + if (nd.ni_vp->v_iflag & VI_DOOMED) { + return (1); + } + } + nd.ni_vp->v_vflag |= VV_MD; + VOP_UNLOCK(nd.ni_vp, 0); + + sc->vnode = nd.ni_vp; + sc->cred = crhold(td->td_ucred); + + return (0); +} + +static int +vtblk_notify(struct beri_vtblk_softc *sc) +{ + struct vqueue_info *vq; + int queue; + int reg; + + vq = &sc->vs_queues[0]; + if (!vq_ring_ready(vq)) + return (0); + + if (!sc->opened) + return (0); + + reg = READ2(sc, VIRTIO_MMIO_QUEUE_NOTIFY); + queue = be16toh(reg); + + KASSERT(queue == 0, ("we support single queue only")); + + /* Process new descriptors */ + vq = &sc->vs_queues[queue]; + vq->vq_save_used = be16toh(vq->vq_used->idx); + while (vq_has_descs(vq)) + vtblk_proc(sc, vq); + + /* Interrupt other side */ + PIO_SET(sc->pio_send, Q_INTR, 1); + + return (0); +} + +static int +vq_init(struct beri_vtblk_softc *sc) +{ + struct vqueue_info *vq; + uint8_t *base; + int size; + int reg; + int pfn; + + vq = &sc->vs_queues[0]; + vq->vq_qsize = NUM_QUEUES; + + reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN); + pfn = be32toh(reg); + vq->vq_pfn = pfn; + + size = vring_size(vq->vq_qsize, VRING_ALIGN); + base = paddr_map(sc->beri_mem_offset, + (pfn << PAGE_SHIFT), size); + + /* First pages are descriptors */ + vq->vq_desc = (struct vring_desc *)base; + base += vq->vq_qsize * sizeof(struct vring_desc); + + /* Then avail ring */ + vq->vq_avail = (struct vring_avail *)base; + base += (2 + vq->vq_qsize + 1) * sizeof(uint16_t); + + /* Then it's rounded up to the next page */ + base = (uint8_t *)roundup2((uintptr_t)base, VRING_ALIGN); + + /* And the last pages are the used ring */ + vq->vq_used = (struct vring_used *)base; + + /* Mark queue as allocated, and start at 0 when we use it. */ + vq->vq_flags = VQ_ALLOC; + vq->vq_last_avail = 0; + + return (0); +} + + +static void +vtblk_thread(void *arg) +{ + struct beri_vtblk_softc *sc; + int err; + + sc = arg; + + sx_xlock(&sc->sc_mtx); + for (;;) { + err = msleep(sc, &sc->sc_mtx, PCATCH | PZERO, "prd", hz); + vtblk_notify(sc); + } + sx_xunlock(&sc->sc_mtx); + + kthread_exit(); +} + +static int +setup_pio(struct beri_vtblk_softc *sc, char *name, device_t *dev) +{ + phandle_t pio_node; + struct fdt_ic *ic; + phandle_t xref; + phandle_t node; + + if ((node = ofw_bus_get_node(sc->dev)) == -1) + return (ENXIO); + + if (OF_searchencprop(node, name, &xref, + sizeof(xref)) == -1) { + return (ENXIO); + } + + pio_node = OF_node_from_xref(xref); + SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) { + if (ic->iph == pio_node) { + *dev = ic->dev; + PIO_CONFIGURE(*dev, PIO_OUT_ALL, + PIO_UNMASK_ALL); + return (0); + } + } + + return (ENXIO); +} + +static int +setup_offset(struct beri_vtblk_softc *sc) +{ + pcell_t dts_value[2]; + phandle_t mem_node; + phandle_t xref; + phandle_t node; + int len; + + if ((node = ofw_bus_get_node(sc->dev)) == -1) + return (ENXIO); + + if (OF_searchencprop(node, "beri-mem", &xref, + sizeof(xref)) == -1) { + return (ENXIO); + } + + mem_node = OF_node_from_xref(xref); + if ((len = OF_getproplen(mem_node, "reg")) <= 0) + return (ENXIO); + OF_getencprop(mem_node, "reg", dts_value, len); + sc->beri_mem_offset = dts_value[0]; + + return (0); +} + +static int +backend_info(struct beri_vtblk_softc *sc) +{ + struct virtio_blk_config *cfg; + uint32_t *s; + int reg; + int i; + + /* Specify that we provide block device */ + reg = htobe32(VIRTIO_ID_BLOCK); + WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg); + + /* The number of queues we support */ + reg = htobe16(NUM_QUEUES); + WRITE2(sc, VIRTIO_MMIO_QUEUE_NUM, reg); + + /* Our features */ + reg = htobe32(VIRTIO_RING_F_INDIRECT_DESC + | VIRTIO_BLK_F_BLK_SIZE + | VIRTIO_BLK_F_SEG_MAX); + WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg); + + cfg = sc->cfg; + cfg->capacity = htobe64(sc->mdio->md_mediasize / DEV_BSIZE); + cfg->size_max = 0; /* not negotiated */ + cfg->seg_max = htobe32(VTBLK_MAXSEGS); + cfg->blk_size = htobe32(DEV_BSIZE); + + s = (uint32_t *)cfg; + + for (i = 0; i < sizeof(struct virtio_blk_config); i+=4) { + WRITE4(sc, VIRTIO_MMIO_CONFIG + i, *s); + s+=1; + } + + sprintf(sc->ident, "Virtio block backend"); + + return (0); +} + +static void +vtblk_intr(void *arg) +{ + struct beri_vtblk_softc *sc; + int pending; + int reg; + + sc = arg; + + reg = PIO_READ(sc->pio_recv); + + /* Ack */ + PIO_SET(sc->pio_recv, reg, 0); + + pending = htobe32(reg); + + if (pending & Q_PFN) { + vq_init(sc); + } + + if (pending & Q_NOTIFY) { + wakeup(sc); + } +} + +static int +beri_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, + int flags, struct thread *td) +{ + struct beri_vtblk_softc *sc; + int err; + + sc = dev->si_drv1; + + switch (cmd) { + case MDIOCATTACH: + /* take file as argument */ + if (sc->vnode != NULL) { + /* Already opened */ + return (1); + } + sc->mdio = (struct md_ioctl *)addr; + backend_info(sc); + DPRINTF("opening file, td 0x%08x\n", (int)td); + err = open_file(sc, td); + if (err) + return (err); + PIO_SETUP_IRQ(sc->pio_recv, vtblk_intr, sc); + sc->opened = 1; + break; + case MDIOCDETACH: + if (sc->vnode == 0) { + /* File not opened */ + return (1); + } + sc->opened = 0; + DPRINTF("closing file, td 0x%08x\n", (int)td); + err = close_file(sc, td); + if (err) + return (err); + PIO_TEARDOWN_IRQ(sc->pio_recv); + break; + default: + break; + } + + return (0); +} + +static struct cdevsw beri_cdevsw = { + .d_version = D_VERSION, + .d_ioctl = beri_ioctl, + .d_name = "virtio block backend", +}; + +static int +beri_vtblk_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-vtblk")) + return (ENXIO); + + device_set_desc(dev, "SRI-Cambridge BERI block"); + return (BUS_PROBE_DEFAULT); +} + +static int +beri_vtblk_attach(device_t dev) +{ + struct beri_vtblk_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, beri_spec, sc->res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + /* Memory interface */ + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + sc->cfg = malloc(sizeof(struct virtio_blk_config), + M_DEVBUF, M_NOWAIT|M_ZERO); + + sx_init(&sc->sc_mtx, device_get_nameunit(sc->dev)); + + error = kthread_add(vtblk_thread, sc, NULL, &sc->vtblk_ktd, + 0, 0, "beri_virtio_block"); + if (error) { + device_printf(dev, "cannot create kthread\n"); + return (ENXIO); + } + + if (setup_offset(sc) != 0) + return (ENXIO); + if (setup_pio(sc, "pio-send", &sc->pio_send) != 0) + return (ENXIO); + if (setup_pio(sc, "pio-recv", &sc->pio_recv) != 0) + return (ENXIO); + + sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL, + S_IRWXU, "beri_vtblk"); + if (sc->cdev == NULL) { + device_printf(dev, "Failed to create character device.\n"); + return (ENXIO); + } + + sc->cdev->si_drv1 = sc; + return (0); +} + +static device_method_t beri_vtblk_methods[] = { + DEVMETHOD(device_probe, beri_vtblk_probe), + DEVMETHOD(device_attach, beri_vtblk_attach), + { 0, 0 } +}; + +static driver_t beri_vtblk_driver = { + "beri_vtblk", + beri_vtblk_methods, + sizeof(struct beri_vtblk_softc), +}; + +static devclass_t beri_vtblk_devclass; + +DRIVER_MODULE(beri_vtblk, simplebus, beri_vtblk_driver, + beri_vtblk_devclass, 0, 0); diff --git a/sys/dev/drm2/drm_drv.c b/sys/dev/drm2/drm_drv.c index 81fcee3dbe7c..d86cbbd27ccc 100644 --- a/sys/dev/drm2/drm_drv.c +++ b/sys/dev/drm2/drm_drv.c @@ -905,7 +905,7 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) { /* The array entries begin at DRM_COMMAND_BASE ioctl nr */ nr -= DRM_COMMAND_BASE; - if (nr > dev->driver->max_ioctl) { + if (nr >= dev->driver->max_ioctl) { DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n", nr, dev->driver->max_ioctl); return EINVAL; diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 4796a915f2e0..335aa01d95c9 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -188,6 +188,7 @@ static char *igb_strings[] = { /********************************************************************* * Function prototypes *********************************************************************/ +static int igb_per_unit_num_queues(SYSCTL_HANDLER_ARGS); static int igb_probe(device_t); static int igb_attach(device_t); static int igb_detach(device_t); @@ -493,6 +494,11 @@ igb_attach(device_t dev) OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, igb_sysctl_nvm_info, "I", "NVM Information"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "num_queues", CTLTYPE_INT | CTLFLAG_RD, + adapter, 0, igb_per_unit_num_queues, "I", "Number of Queues"); + igb_set_sysctl_value(adapter, "enable_aim", "Interrupt Moderation", &adapter->enable_aim, igb_enable_aim); @@ -2831,6 +2837,7 @@ igb_setup_msix(struct adapter *adapter) { device_t dev = adapter->dev; int bar, want, queues, msgs, maxqueues; + int n_queues; /* tuneable override */ if (igb_enable_msix == 0) @@ -2858,8 +2865,18 @@ igb_setup_msix(struct adapter *adapter) goto msi; } - /* Figure out a reasonable auto config value */ - queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; + n_queues = 0; + /* try more specific tunable, then global, then finally default to boot time tunable if set. */ + if (device_getenv_int(dev, "num_queues", &n_queues) != 0) { + device_printf(dev, "using specific tunable num_queues=%d", n_queues); + } else if (TUNABLE_INT_FETCH("hw.igb.num_queues", &n_queues) != 0) { + if (igb_num_queues != n_queues) { + device_printf(dev, "using global tunable hw.igb.num_queues=%d", n_queues); + igb_num_queues = n_queues; + } + } else { + n_queues = igb_num_queues; + } #ifdef RSS /* If we're doing RSS, clamp at the number of RSS buckets */ @@ -2867,10 +2884,12 @@ igb_setup_msix(struct adapter *adapter) queues = rss_getnumbuckets(); #endif - - /* Manual override */ - if (igb_num_queues != 0) - queues = igb_num_queues; + if (n_queues != 0) { + queues = n_queues; + } else { + /* Figure out a reasonable auto config value */ + queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; + } /* Sanity check based on HW */ switch (adapter->hw.mac.type) { @@ -2893,12 +2912,17 @@ igb_setup_msix(struct adapter *adapter) maxqueues = 1; break; } - if (queues > maxqueues) + if (queues > maxqueues) { + device_printf(adapter->dev, "requested %d queues, but max for this adapter is %d\n", + queues, maxqueues); queues = maxqueues; - - /* Manual override */ - if (igb_num_queues != 0) - queues = igb_num_queues; + } else if (queues == 0) { + queues = 1; + } else if (queues < 0) { + device_printf(adapter->dev, "requested %d queues, but min for this adapter is %d\n", + queues, 1); + queues = 1; + } /* ** One vector (RX/TX pair) per queue @@ -6384,3 +6408,14 @@ igb_sysctl_eee(SYSCTL_HANDLER_ARGS) IGB_CORE_UNLOCK(adapter); return (0); } + +static int +igb_per_unit_num_queues(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter; + + adapter = (struct adapter *) arg1; + + return sysctl_handle_int(oidp, &adapter->num_queues, 0, req); +} + diff --git a/sys/dev/hwpmc/hwpmc_mpc7xxx.c b/sys/dev/hwpmc/hwpmc_mpc7xxx.c index 7162257155d8..171523b80b50 100644 --- a/sys/dev/hwpmc/hwpmc_mpc7xxx.c +++ b/sys/dev/hwpmc/hwpmc_mpc7xxx.c @@ -578,9 +578,9 @@ mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu) } /* Clear the MMCRs, and set FC, to disable all PMCs. */ - mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); + mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | + SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE); mtspr(SPR_MMCR1, 0); - mtmsr(mfmsr() | PSL_PMM); return 0; } @@ -667,7 +667,6 @@ mpc7xxx_intr(int cpu, struct trapframe *tf) uint32_t config; struct pmc *pm; struct powerpc_cpu *pac; - pmc_value_t v; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); @@ -679,8 +678,7 @@ mpc7xxx_intr(int cpu, struct trapframe *tf) pac = powerpc_pcpu[cpu]; - config = mfspr(SPR_MMCR0); - mtspr(SPR_MMCR0, config | SPR_MMCR0_FC); + config = mfspr(SPR_MMCR0) & ~SPR_MMCR0_FC; /* * look for all PMCs that have interrupted: @@ -704,22 +702,22 @@ mpc7xxx_intr(int cpu, struct trapframe *tf) if (pm->pm_state != PMC_STATE_RUNNING) continue; - /* Stop the PMC, reload count. */ - v = pm->pm_sc.pm_reloadcount; - mpc7xxx_pmcn_write(i, v); - - /* Restart the counter if logging succeeded. */ + /* Stop the counter if logging fails. */ error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, TRAPF_USERMODE(tf)); if (error != 0) mpc7xxx_stop_pmc(cpu, i); - atomic_add_int(retval ? &pmc_stats.pm_intr_processed : - &pmc_stats.pm_intr_ignored, 1); + /* reload count. */ + mpc7xxx_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); } + atomic_add_int(retval ? &pmc_stats.pm_intr_processed : + &pmc_stats.pm_intr_ignored, 1); + /* Re-enable PERF exceptions. */ - mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); + if (retval) + mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE); return (retval); } diff --git a/sys/dev/hwpmc/hwpmc_ppc970.c b/sys/dev/hwpmc/hwpmc_ppc970.c index 1ff2fd83f2a8..c6e8f4c7b6d8 100644 --- a/sys/dev/hwpmc/hwpmc_ppc970.c +++ b/sys/dev/hwpmc/hwpmc_ppc970.c @@ -481,7 +481,6 @@ ppc970_intr(int cpu, struct trapframe *tf) { struct pmc *pm; struct powerpc_cpu *pac; - pmc_value_t v; uint32_t config; int i, error, retval; @@ -503,8 +502,7 @@ ppc970_intr(int cpu, struct trapframe *tf) * If found, we call a helper to process the interrupt. */ - config = mfspr(SPR_970MMCR0); - mtspr(SPR_970MMCR0, config | SPR_MMCR0_FC); + config = mfspr(SPR_970MMCR0) & ~SPR_MMCR0_FC; for (i = 0; i < PPC970_MAX_PMCS; i++) { if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { @@ -519,24 +517,21 @@ ppc970_intr(int cpu, struct trapframe *tf) if (pm->pm_state != PMC_STATE_RUNNING) continue; - /* Stop the PMC, reload count. */ - v = pm->pm_sc.pm_reloadcount; - - ppc970_pmcn_write(i, v); - - /* Restart the counter if logging succeeded. */ error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, TRAPF_USERMODE(tf)); - mtspr(SPR_970MMCR0, config); if (error != 0) ppc970_stop_pmc(cpu, i); - atomic_add_int(retval ? &pmc_stats.pm_intr_processed : - &pmc_stats.pm_intr_ignored, 1); + /* reload sampling count. */ + ppc970_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); } + atomic_add_int(retval ? &pmc_stats.pm_intr_processed : + &pmc_stats.pm_intr_ignored, 1); + /* Re-enable PERF exceptions. */ - mtspr(SPR_970MMCR0, mfspr(SPR_970MMCR0) | SPR_MMCR0_PMXE); + if (retval) + mtspr(SPR_970MMCR0, config | SPR_MMCR0_PMXE); return (retval); } @@ -572,10 +567,10 @@ ppc970_pcpu_init(struct pmc_mdep *md, int cpu) /* Clear the MMCRs, and set FC, to disable all PMCs. */ /* 970 PMC is not counted when set to 0x08 */ - mtspr(SPR_970MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | - SPR_MMCR0_PMCNCE | SPR_970MMCR0_PMC1SEL(0x8) | SPR_970MMCR0_PMC2SEL(0x8)); + mtspr(SPR_970MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | + SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE | + SPR_970MMCR0_PMC1SEL(0x8) | SPR_970MMCR0_PMC2SEL(0x8)); mtspr(SPR_970MMCR1, 0x4218420); - mtmsr(mfmsr() | PSL_PMM); return 0; } @@ -585,7 +580,6 @@ ppc970_pcpu_fini(struct pmc_mdep *md, int cpu) { register_t mmcr0 = mfspr(SPR_MMCR0); - mtmsr(mfmsr() & ~PSL_PMM); mmcr0 |= SPR_MMCR0_FC; mmcr0 &= ~SPR_MMCR0_PMXE; mtspr(SPR_MMCR0, mmcr0); diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 906c41d66c18..de0d0743d8c2 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$"); #define ID_AVOTON 0x1f3c8086 #define ID_COLETOCRK 0x23B08086 #define ID_LPT 0x8c228086 +#define ID_WCPT 0x8ca28086 #define PCIS_SERIALBUS_SMBUS_PROGIF 0x00 @@ -197,6 +198,9 @@ ichsmb_pci_probe(device_t dev) case ID_LPT: device_set_desc(dev, "Intel Lynx Point SMBus controller"); break; + case ID_WCPT: + device_set_desc(dev, "Intel Wildcat Point SMBus controller"); + break; case ID_COLETOCRK: device_set_desc(dev, "Intel Coleto Creek SMBus controller"); break; diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c index f28f5e04f6b3..fdaac711ce3a 100644 --- a/sys/dev/ichwd/ichwd.c +++ b/sys/dev/ichwd/ichwd.c @@ -194,6 +194,9 @@ static struct ichwd_device ichwd_devices[] = { { DEVICEID_LPT0, "Intel Lynx Point watchdog timer", 10 }, { DEVICEID_LPT1, "Intel Lynx Point watchdog timer", 10 }, { DEVICEID_LPT2, "Intel Lynx Point watchdog timer", 10 }, + { DEVICEID_WCPT2, "Intel Wildcat Point watchdog timer", 10 }, + { DEVICEID_WCPT4, "Intel Wildcat Point watchdog timer", 10 }, + { DEVICEID_WCPT6, "Intel Wildcat Point watchdog timer", 10 }, { DEVICEID_DH89XXCC_LPC, "Intel DH89xxCC watchdog timer", 10 }, { DEVICEID_COLETOCRK_LPC, "Intel Coleto Creek watchdog timer", 10 }, { 0, NULL, 0 }, diff --git a/sys/dev/ichwd/ichwd.h b/sys/dev/ichwd/ichwd.h index 6f0c7173efd7..0699279f2d43 100644 --- a/sys/dev/ichwd/ichwd.h +++ b/sys/dev/ichwd/ichwd.h @@ -210,6 +210,9 @@ struct ichwd_softc { #define DEVICEID_LPT29 0x8c5d #define DEVICEID_LPT30 0x8c5e #define DEVICEID_LPT31 0x8c5f +#define DEVICEID_WCPT2 0x8cc2 +#define DEVICEID_WCPT4 0x8cc4 +#define DEVICEID_WCPT6 0x8cc6 /* ICH LPC Interface Bridge Registers (ICH5 and older) */ #define ICH_GEN_STA 0xd4 diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 8ac6bf2152f5..46361b95e482 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1219,7 +1219,7 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) * work for them). */ if (IS_FC(isp) && isp->isp_nchan > 1) { - if (!IS_24XX(isp) || (fwt & ISP2400_FW_ATTR_MULTIID) == 0) { + if (!ISP_CAP_MULTI_ID(isp)) { isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, only can enable 1 of %d channels", isp->isp_nchan); isp->isp_nchan = 1; } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 29960d75936f..31a1db6b3089 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -894,7 +894,7 @@ is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun) ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); SLIST_FOREACH(tptr, lhp, next) { - if (xpt_path_lun_id(tptr->owner) == lun) { + if (tptr->ts_lun == lun) { return (1); } } @@ -926,16 +926,13 @@ get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun) { tstate_t *tptr = NULL; struct tslist *lhp; - int i; if (bus < isp->isp_nchan) { - for (i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - SLIST_FOREACH(tptr, lhp, next) { - if (xpt_path_lun_id(tptr->owner) == lun) { - tptr->hold++; - return (tptr); - } + ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); + SLIST_FOREACH(tptr, lhp, next) { + if (tptr->ts_lun == lun) { + tptr->hold++; + return (tptr); } } } @@ -1149,6 +1146,7 @@ create_lun_state(ispsoftc_t *isp, int bus, struct cam_path *path, tstate_t **rsl if (tptr == NULL) { return (CAM_RESRC_UNAVAIL); } + tptr->ts_lun = lun; status = xpt_create_path(&tptr->owner, NULL, xpt_path_path_id(path), xpt_path_target_id(path), lun); if (status != CAM_REQ_CMP) { free(tptr, M_DEVBUF); @@ -1166,7 +1164,7 @@ create_lun_state(ispsoftc_t *isp, int bus, struct cam_path *path, tstate_t **rsl tptr->ntpool[i].next = &tptr->ntpool[i+1]; tptr->ntfree = tptr->ntpool; tptr->hold = 1; - ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp); + ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp); SLIST_INSERT_HEAD(lhp, tptr, next); *rslt = tptr; ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, path, "created tstate\n"); @@ -1197,7 +1195,7 @@ destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr) xpt_done(ccb); } } while (ccb); - ISP_GET_PC_ADDR(isp, cam_sim_bus(xpt_path_sim(tptr->owner)), lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp); + ISP_GET_PC_ADDR(isp, cam_sim_bus(xpt_path_sim(tptr->owner)), lun_hash[LUN_HASH_FUNC(tptr->ts_lun)], lhp); SLIST_REMOVE(lhp, tptr, tstate, next); ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "destroyed tstate\n"); xpt_free_path(tptr->owner); @@ -1373,7 +1371,7 @@ isp_enable_deferred_luns(ispsoftc_t *isp, int bus) SLIST_FOREACH(tptr, lhp, next) { tptr->hold++; if (tptr->enabled == 0) { - if (isp_enable_deferred(isp, bus, xpt_path_lun_id(tptr->owner)) == CAM_REQ_CMP) { + if (isp_enable_deferred(isp, bus, tptr->ts_lun) == CAM_REQ_CMP) { tptr->enabled = 1; n++; } @@ -6042,7 +6040,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) */ tptr = get_lun_statep_from_tag(isp, chan, abts->abts_rxid_task); if (tptr) { - nt->nt_lun = xpt_path_lun_id(tptr->owner); + nt->nt_lun = tptr->ts_lun; rls_lun_statep(isp, tptr); } else { nt->nt_lun = LUN_ANY; @@ -6140,10 +6138,9 @@ isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn) return (seed); } return (0x400000007F000009ull); - } else { - seed = iswwnn ? fc->def_wwnn : fc->def_wwpn; } + seed = iswwnn ? fc->def_wwnn : fc->def_wwpn; /* * For channel zero just return what we have. For either ACTIVE or @@ -6166,11 +6163,9 @@ isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn) if (seed) { return (seed); } - if (isactive) { + seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn : ISP_FC_PC(isp, 0)->def_wwpn; + if (seed == 0) seed = iswwnn ? FCPARAM(isp, 0)->isp_wwnn_nvram : FCPARAM(isp, 0)->isp_wwpn_nvram; - } else { - seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn : ISP_FC_PC(isp, 0)->def_wwpn; - } if (((seed >> 60) & 0xf) == 2) { /* diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 812385ea2cf1..d4944be8a8d6 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -95,7 +95,7 @@ void isp_put_ecmd(struct ispsoftc *, isp_ecmd_t *); #define ISP_TARGET_FUNCTIONS 1 #define ATPDPSIZE 4096 -#define ATPDPHASHSIZE 16 +#define ATPDPHASHSIZE 32 #define ATPDPHASH(x) ((((x) >> 24) ^ ((x) >> 16) ^ ((x) >> 8) ^ (x)) & \ ((ATPDPHASHSIZE) - 1)) @@ -164,6 +164,7 @@ typedef struct isp_timed_notify_ack { TAILQ_HEAD(isp_ccbq, ccb_hdr); typedef struct tstate { SLIST_ENTRY(tstate) next; + lun_id_t ts_lun; struct cam_path *owner; struct isp_ccbq waitq; /* waiting CCBs */ struct ccb_hdr_slist atios; diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index b6d594515547..cb9c4ffefdf3 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -2369,7 +2369,7 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr) if (chan < isp->isp_nchan) { fcp = FCPARAM(isp, chan); - for (i = 0; i < MAX_FC_TARG; i++) { + for (i = MAX_FC_TARG - 1; i >= 0; i--) { fcportdb_t *lp = &fcp->portdb[i]; if (lp->target_mode == 0) { @@ -2392,7 +2392,7 @@ isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t ** if (chan < isp->isp_nchan) { fcp = FCPARAM(isp, chan); - for (i = 0; i < MAX_FC_TARG; i++) { + for (i = MAX_FC_TARG - 1; i >= 0; i--) { fcportdb_t *lp = &fcp->portdb[i]; if (lp->target_mode == 0) { @@ -2418,7 +2418,7 @@ isp_find_pdb_by_sid(ispsoftc_t *isp, int chan, uint32_t sid, fcportdb_t **lptr) } fcp = FCPARAM(isp, chan); - for (i = 0; i < MAX_FC_TARG; i++) { + for (i = MAX_FC_TARG - 1; i >= 0; i--) { fcportdb_t *lp = &fcp->portdb[i]; if (lp->target_mode == 0) { diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index df47b3db0b0c..9ac70eeac5e4 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -103,6 +103,7 @@ static char *ixgbe_strings[] = { /********************************************************************* * Function prototypes *********************************************************************/ +static int ixgbe_per_unit_num_queues(SYSCTL_HANDLER_ARGS); static int ixgbe_probe(device_t); static int ixgbe_attach(device_t); static int ixgbe_detach(device_t); @@ -473,6 +474,11 @@ ixgbe_attach(device_t dev) OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_set_advertise, "I", "Link Speed"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "num_queues", CTLTYPE_INT | CTLFLAG_RD, + adapter, 0, ixgbe_per_unit_num_queues, "I", "Number of Queues"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "ts", CTLTYPE_INT | CTLFLAG_RW, adapter, @@ -2516,6 +2522,7 @@ ixgbe_setup_msix(struct adapter *adapter) { device_t dev = adapter->dev; int rid, want, queues, msgs; + int n_queues; /* Override by tuneable */ if (ixgbe_enable_msix == 0) @@ -2548,15 +2555,29 @@ ixgbe_setup_msix(struct adapter *adapter) queues = rss_getnumbuckets(); #endif - if (ixgbe_num_queues != 0) - queues = ixgbe_num_queues; + /* try more specific tunable, then global, then finally default to boot time tunable if set. */ + if (device_getenv_int(dev, "num_queues", &n_queues) != 0) { + device_printf(dev, "using specific tunable numqueues=%d", n_queues); + } else if (TUNABLE_INT_FETCH("hw.ix.num_queues", &n_queues) != 0) { + if (ixgbe_num_queues != n_queues) { + device_printf(dev, "using global tunable num_queues=%d", n_queues); + ixgbe_num_queues = n_queues; + } + } else { + n_queues = ixgbe_num_queues; + } + + if (n_queues < 0) { + device_printf(dev, "tunable < 0, resetting to default"); + n_queues = 0; + } + + if (n_queues != 0) + queues = n_queues; /* Set max queues to 8 when autoconfiguring */ else if ((ixgbe_num_queues == 0) && (queues > 8)) queues = 8; - /* reflect correct sysctl value */ - ixgbe_num_queues = queues; - /* ** Want one vector (RX/TX pair) per queue ** plus an additional for Link. @@ -5943,6 +5964,16 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS) return error; } +static int +ixgbe_per_unit_num_queues(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter; + + adapter = (struct adapter *) arg1; + + return sysctl_handle_int(oidp, &adapter->num_queues, 0, req); +} + /* ** Control link advertise speed: ** 1 - advertise only 1G diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index c13716e9351c..925ff3fd2d82 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -86,6 +86,7 @@ static const struct { { HDA_INTEL_PPT1, "Intel Panther Point", 0, 0 }, { HDA_INTEL_LPT1, "Intel Lynx Point", 0, 0 }, { HDA_INTEL_LPT2, "Intel Lynx Point", 0, 0 }, + { HDA_INTEL_WCPT, "Intel Wildcat Point", 0, 0 }, { HDA_INTEL_WELLS1, "Intel Wellsburg", 0, 0 }, { HDA_INTEL_WELLS2, "Intel Wellsburg", 0, 0 }, { HDA_INTEL_LPTLP1, "Intel Lynx Point-LP", 0, 0 }, diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h index 0fc2c0f5c9ac..153426d167eb 100644 --- a/sys/dev/sound/pci/hda/hdac.h +++ b/sys/dev/sound/pci/hda/hdac.h @@ -62,6 +62,7 @@ #define HDA_INTEL_SCH HDA_MODEL_CONSTRUCT(INTEL, 0x811b) #define HDA_INTEL_LPT1 HDA_MODEL_CONSTRUCT(INTEL, 0x8c20) #define HDA_INTEL_LPT2 HDA_MODEL_CONSTRUCT(INTEL, 0x8c21) +#define HDA_INTEL_WCPT HDA_MODEL_CONSTRUCT(INTEL, 0x8ca0) #define HDA_INTEL_WELLS1 HDA_MODEL_CONSTRUCT(INTEL, 0x8d20) #define HDA_INTEL_WELLS2 HDA_MODEL_CONSTRUCT(INTEL, 0x8d21) #define HDA_INTEL_LPTLP1 HDA_MODEL_CONSTRUCT(INTEL, 0x9c20) diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index a65fd90d814d..748d18afc78d 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -127,6 +127,7 @@ static const struct pci_id pci_ns8250_ids[] = { { 0x8086, 0x8813, 0xffff, 0, "Intel EG20T Serial Port 2", 0x10 }, { 0x8086, 0x8814, 0xffff, 0, "Intel EG20T Serial Port 3", 0x10 }, { 0x8086, 0x8c3d, 0xffff, 0, "Intel Lynx Point KT Controller", 0x10 }, +{ 0x8086, 0x8cbd, 0xffff, 0, "Intel Wildcat Point KT Controller", 0x10 }, { 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 }, { 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 }, { 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 }, diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c index 022540014e83..e71c2eb601d5 100644 --- a/sys/dev/usb/controller/ehci_pci.c +++ b/sys/dev/usb/controller/ehci_pci.c @@ -164,6 +164,12 @@ ehci_pci_match(device_t self) return ("Intel Lynx Point USB 2.0 controller USB-A"); case 0x8c2d8086: return ("Intel Lynx Point USB 2.0 controller USB-B"); + case 0x8ca68086: + return ("Intel Wildcat Point USB 2.0 controller USB-A"); + case 0x8cad8086: + return ("Intel Wildcat Point USB 2.0 controller USB-B"); + case 0x9c268086: + return ("Intel Lynx Point LP USB 2.0 controller USB"); case 0x00e01033: return ("NEC uPD 720100 USB 2.0 controller"); diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c index 36ca677b768f..fa83d6133b01 100644 --- a/sys/dev/usb/controller/ohci_pci.c +++ b/sys/dev/usb/controller/ohci_pci.c @@ -175,6 +175,8 @@ ohci_pci_match(device_t self) case 0x0019106b: return ("Apple KeyLargo USB controller"); + case 0x003f106b: + return ("Apple KeyLargo/Intrepid USB controller"); default: break; diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index ef297d1bf2ab..b515edf7f8fe 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -109,6 +109,8 @@ xhci_pci_match(device_t self) return ("Intel Panther Point USB 3.0 controller"); case 0x8c318086: return ("Intel Lynx Point USB 3.0 controller"); + case 0x8cb18086: + return ("Intel Wildcat Point USB 3.0 controller"); default: break; diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c index cee94aa5b3ea..79e2e5e449cb 100644 --- a/sys/dev/usb/quirk/usb_quirk.c +++ b/sys/dev/usb/quirk/usb_quirk.c @@ -253,6 +253,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(LEXAR, CF_READER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), USB_QUIRK(LEXAR, JUMPSHOT, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), + USB_QUIRK(LEXAR, JUMPDRIVE, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), USB_QUIRK(LOGITEC, LDR_H443SU2, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(LOGITEC, LDR_H443U2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,), diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 5ec9cdc63ae7..f26259f0cbe3 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -2604,6 +2604,7 @@ product LENOVO ETHERNET 0x7203 USB 2.0 Ethernet /* Lexar products */ product LEXAR JUMPSHOT 0x0001 jumpSHOT CompactFlash Reader product LEXAR CF_READER 0xb002 USB CF Reader +product LEXAR JUMPDRIVE 0xa833 USB Jumpdrive Flash Drive /* Lexmark products */ product LEXMARK S2450 0x0009 Optra S 2450 diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c index a97e0a9fa139..5a00ee157a54 100644 --- a/sys/fs/procfs/procfs_status.c +++ b/sys/fs/procfs/procfs_status.c @@ -125,9 +125,9 @@ procfs_doprocstatus(PFS_FILL_ARGS) if (p->p_flag & P_INMEM) { struct timeval start, ut, st; - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &ut, &st); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); start = p->p_stats->p_start; timevaladd(&start, &boottime); sbuf_printf(sb, " %jd,%ld %jd,%ld %jd,%ld", diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index c3af9f62a705..751e73294761 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1060,6 +1060,11 @@ sys_sigreturn(td, uap) if (error != 0) return (error); ucp = &uc; + if ((ucp->uc_mcontext.mc_flags & ~_MC_FLAG_MASK) != 0) { + uprintf("pid %d (%s): sigreturn mc_flags %x\n", p->p_pid, + td->td_name, ucp->uc_mcontext.mc_flags); + return (EINVAL); + } regs = td->td_frame; eflags = ucp->uc_mcontext.mc_eflags; if (eflags & PSL_VM) { @@ -3858,7 +3863,8 @@ set_mcontext(struct thread *td, const mcontext_t *mcp) int eflags, ret; tp = td->td_frame; - if (mcp->mc_len != sizeof(*mcp)) + if (mcp->mc_len != sizeof(*mcp) || + (mcp->mc_flags & ~_MC_FLAG_MASK) != 0) return (EINVAL); eflags = (mcp->mc_eflags & PSL_USERCHANGE) | (tp->tf_eflags & ~PSL_USERCHANGE); diff --git a/sys/i386/include/asm.h b/sys/i386/include/asm.h index 378a58549ff7..b2d4a6b28902 100644 --- a/sys/i386/include/asm.h +++ b/sys/i386/include/asm.h @@ -38,7 +38,7 @@ #include -#ifdef __PIC__ +#ifdef PIC #define PIC_PROLOGUE \ pushl %ebx; \ call 1f; \ diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index a065b75bfda0..e903f4cc89f5 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -603,9 +603,9 @@ proc0_post(void *dummy __unused) sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { microuptime(&p->p_stats->p_start); - PROC_SLOCK(p); + PROC_STATLOCK(p); rufetch(p, &ru); /* Clears thread stats */ - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); p->p_rux.rux_runtime = 0; p->p_rux.rux_uticks = 0; p->p_rux.rux_sticks = 0; diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 79a294d37e3d..6aa35234cb1d 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -432,16 +432,16 @@ hardclock_cpu(int usermode) flags = 0; if (usermode && timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) { - PROC_SLOCK(p); + PROC_ITIMLOCK(p); if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) flags |= TDF_ALRMPEND | TDF_ASTPENDING; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) { - PROC_SLOCK(p); + PROC_ITIMLOCK(p); if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) flags |= TDF_PROFPEND | TDF_ASTPENDING; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } thread_lock(td); sched_tick(1); @@ -520,18 +520,18 @@ hardclock_cnt(int cnt, int usermode) flags = 0; if (usermode && timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) { - PROC_SLOCK(p); + PROC_ITIMLOCK(p); if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick * cnt) == 0) flags |= TDF_ALRMPEND | TDF_ASTPENDING; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) { - PROC_SLOCK(p); + PROC_ITIMLOCK(p); if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick * cnt) == 0) flags |= TDF_PROFPEND | TDF_ASTPENDING; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } thread_lock(td); sched_tick(cnt); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 1e4c0956474d..21daee162462 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -614,7 +614,9 @@ exit1(struct thread *td, int rv) /* * Save our children's rusage information in our exit rusage. */ + PROC_STATLOCK(p); ruadd(&p->p_ru, &p->p_rux, &p->p_stats->p_cru, &p->p_crux); + PROC_STATUNLOCK(p); /* * Make sure the scheduler takes this thread out of its tables etc. @@ -990,8 +992,6 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, return (0); } - PROC_SLOCK(p); - if (siginfo != NULL) { bzero(siginfo, sizeof(*siginfo)); siginfo->si_errno = 0; @@ -1038,7 +1038,9 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, if (wrusage != NULL) { rup = &wrusage->wru_self; *rup = p->p_ru; + PROC_STATLOCK(p); calcru(p, &rup->ru_utime, &rup->ru_stime); + PROC_STATUNLOCK(p); rup = &wrusage->wru_children; *rup = p->p_stats->p_cru; @@ -1046,10 +1048,10 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, } if (p->p_state == PRS_ZOMBIE) { + PROC_SLOCK(p); proc_reap(td, p, status, options); return (-1); } - PROC_SUNLOCK(p); PROC_UNLOCK(p); return (1); } diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index d9849081396e..e1469b7a00c9 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -969,6 +969,9 @@ mutex_init(void) blocked_lock.mtx_lock = 0xdeadc0de; /* Always blocked. */ mtx_init(&proc0.p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK); mtx_init(&proc0.p_slock, "process slock", NULL, MTX_SPIN | MTX_RECURSE); + mtx_init(&proc0.p_statmtx, "pstatl", NULL, MTX_SPIN); + mtx_init(&proc0.p_itimmtx, "pitiml", NULL, MTX_SPIN); + mtx_init(&proc0.p_profmtx, "pprofl", NULL, MTX_SPIN); mtx_init(&devmtx, "cdev", NULL, MTX_DEF); mtx_lock(&Giant); } diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 495139fa368d..009ccceb79e0 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -228,6 +228,9 @@ proc_init(void *mem, int size, int flags) bzero(&p->p_mtx, sizeof(struct mtx)); mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK); mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_RECURSE); + mtx_init(&p->p_statmtx, "pstatl", NULL, MTX_SPIN); + mtx_init(&p->p_itimmtx, "pitiml", NULL, MTX_SPIN); + mtx_init(&p->p_profmtx, "pprofl", NULL, MTX_SPIN); cv_init(&p->p_pwait, "ppwait"); cv_init(&p->p_dbgwait, "dbgwait"); TAILQ_INIT(&p->p_threads); /* all threads in proc */ @@ -872,11 +875,11 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp) kp->ki_fibnum = p->p_fibnum; kp->ki_start = p->p_stats->p_start; timevaladd(&kp->ki_start, &boottime); - PROC_SLOCK(p); + PROC_STATLOCK(p); rufetch(p, &kp->ki_rusage); kp->ki_runtime = cputick2usec(p->p_rux.rux_runtime); calcru(p, &kp->ki_rusage.ru_utime, &kp->ki_rusage.ru_stime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); calccru(p, &kp->ki_childutime, &kp->ki_childstime); /* Some callers want child times in a single value. */ kp->ki_childtime = kp->ki_childstime; @@ -944,7 +947,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread) PROC_LOCK_ASSERT(p, MA_OWNED); if (preferthread) - PROC_SLOCK(p); + PROC_STATLOCK(p); thread_lock(td); if (td->td_wmesg != NULL) strlcpy(kp->ki_wmesg, td->td_wmesg, sizeof(kp->ki_wmesg)); @@ -1030,7 +1033,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread) kp->ki_sigmask = td->td_sigmask; thread_unlock(td); if (preferthread) - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); } /* diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index 84fa31225189..05becea995d2 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -1129,11 +1129,11 @@ racctd(void) microuptime(&wallclock); timevalsub(&wallclock, &p->p_stats->p_start); - PROC_SLOCK(p); + PROC_STATLOCK(p); FOREACH_THREAD_IN_PROC(p, td) ruxagg(p, td); runtime = cputick2usec(p->p_rux.rux_runtime); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); #ifdef notyet KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime")); diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 50ea8ac90df2..56b598f4be18 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -619,11 +619,11 @@ lim_cb(void *arg) */ if (p->p_cpulimit == RLIM_INFINITY) return; - PROC_SLOCK(p); + PROC_STATLOCK(p); FOREACH_THREAD_IN_PROC(p, td) { ruxagg(p, td); } - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { lim_rlimit(p, RLIMIT_CPU, &rlim); if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) { @@ -825,7 +825,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp) uint64_t runtime, u; PROC_LOCK_ASSERT(p, MA_OWNED); - PROC_SLOCK_ASSERT(p, MA_OWNED); + PROC_STATLOCK_ASSERT(p, MA_OWNED); /* * If we are getting stats for the current process, then add in the * stats that this thread has accumulated in its current time slice. @@ -857,7 +857,7 @@ rufetchtd(struct thread *td, struct rusage *ru) uint64_t runtime, u; p = td->td_proc; - PROC_SLOCK_ASSERT(p, MA_OWNED); + PROC_STATLOCK_ASSERT(p, MA_OWNED); THREAD_LOCK_ASSERT(td, MA_OWNED); /* * If we are getting stats for the current thread, then add in the @@ -991,11 +991,11 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup) break; case RUSAGE_THREAD: - PROC_SLOCK(p); + PROC_STATLOCK(p); thread_lock(td); rufetchtd(td, rup); thread_unlock(td); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); break; default: @@ -1042,7 +1042,7 @@ ruxagg_locked(struct rusage_ext *rux, struct thread *td) { THREAD_LOCK_ASSERT(td, MA_OWNED); - PROC_SLOCK_ASSERT(td->td_proc, MA_OWNED); + PROC_STATLOCK_ASSERT(td->td_proc, MA_OWNED); rux->rux_runtime += td->td_incruntime; rux->rux_uticks += td->td_uticks; rux->rux_sticks += td->td_sticks; @@ -1072,7 +1072,7 @@ rufetch(struct proc *p, struct rusage *ru) { struct thread *td; - PROC_SLOCK_ASSERT(p, MA_OWNED); + PROC_STATLOCK_ASSERT(p, MA_OWNED); *ru = p->p_ru; if (p->p_numthreads > 0) { @@ -1093,10 +1093,10 @@ rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up, struct timeval *sp) { - PROC_SLOCK(p); + PROC_STATLOCK(p); rufetch(p, ru); calcru(p, up, sp); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); } /* diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5cdc2cedf1d8..502f334d39da 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -998,8 +998,12 @@ kern_sigprocmask(struct thread *td, int how, sigset_t *set, sigset_t *oset, int error; p = td->td_proc; - if (!(flags & SIGPROCMASK_PROC_LOCKED)) + if ((flags & SIGPROCMASK_PROC_LOCKED) != 0) + PROC_LOCK_ASSERT(p, MA_OWNED); + else PROC_LOCK(p); + mtx_assert(&p->p_sigacts->ps_mtx, (flags & SIGPROCMASK_PS_LOCKED) != 0 + ? MA_OWNED : MA_NOTOWNED); if (oset != NULL) *oset = td->td_sigmask; @@ -1882,6 +1886,30 @@ pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi) } } + +/* + * Recalculate the signal mask and reset the signal disposition after + * usermode frame for delivery is formed. Should be called after + * mach-specific routine, because sysent->sv_sendsig() needs correct + * ps_siginfo and signal mask. + */ +static void +postsig_done(int sig, struct thread *td, struct sigacts *ps) +{ + sigset_t mask; + + mtx_assert(&ps->ps_mtx, MA_OWNED); + td->td_ru.ru_nsignals++; + mask = ps->ps_catchmask[_SIG_IDX(sig)]; + if (!SIGISMEMBER(ps->ps_signodefer, sig)) + SIGADDSET(mask, sig); + kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, + SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); + if (SIGISMEMBER(ps->ps_sigreset, sig)) + sigdflt(ps, sig); +} + + /* * Send a signal caused by a trap to the current thread. If it will be * caught immediately, deliver it with correct code. Otherwise, post it @@ -1891,7 +1919,6 @@ void trapsignal(struct thread *td, ksiginfo_t *ksi) { struct sigacts *ps; - sigset_t mask; struct proc *p; int sig; int code; @@ -1906,7 +1933,6 @@ trapsignal(struct thread *td, ksiginfo_t *ksi) mtx_lock(&ps->ps_mtx); if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) && !SIGISMEMBER(td->td_sigmask, sig)) { - td->td_ru.ru_nsignals++; #ifdef KTRACE if (KTRPOINT(curthread, KTR_PSIG)) ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)], @@ -1914,13 +1940,7 @@ trapsignal(struct thread *td, ksiginfo_t *ksi) #endif (*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], ksi, &td->td_sigmask); - mask = ps->ps_catchmask[_SIG_IDX(sig)]; - if (!SIGISMEMBER(ps->ps_signodefer, sig)) - SIGADDSET(mask, sig); - kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, - SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); - if (SIGISMEMBER(ps->ps_sigreset, sig)) - sigdflt(ps, sig); + postsig_done(sig, td, ps); mtx_unlock(&ps->ps_mtx); } else { /* @@ -2494,9 +2514,11 @@ reschedule_signals(struct proc *p, sigset_t block, int flags) int sig; PROC_LOCK_ASSERT(p, MA_OWNED); + ps = p->p_sigacts; + mtx_assert(&ps->ps_mtx, (flags & SIGPROCMASK_PS_LOCKED) != 0 ? + MA_OWNED : MA_NOTOWNED); if (SIGISEMPTY(p->p_siglist)) return; - ps = p->p_sigacts; SIGSETAND(block, p->p_siglist); while ((sig = sig_ffs(&block)) != 0) { SIGDELSET(block, sig); @@ -2802,7 +2824,7 @@ postsig(sig) struct sigacts *ps; sig_t action; ksiginfo_t ksi; - sigset_t returnmask, mask; + sigset_t returnmask; KASSERT(sig != 0, ("postsig")); @@ -2857,20 +2879,12 @@ postsig(sig) } else returnmask = td->td_sigmask; - mask = ps->ps_catchmask[_SIG_IDX(sig)]; - if (!SIGISMEMBER(ps->ps_signodefer, sig)) - SIGADDSET(mask, sig); - kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, - SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED); - - if (SIGISMEMBER(ps->ps_sigreset, sig)) - sigdflt(ps, sig); - td->td_ru.ru_nsignals++; if (p->p_sig == sig) { p->p_code = 0; p->p_sig = 0; } (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); + postsig_done(sig, td, ps); } return (1); } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index ec084ed57c1d..ea076b92144a 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -470,6 +470,9 @@ thread_exit(void) PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_OUT); #endif PROC_UNLOCK(p); + PROC_STATLOCK(p); + thread_lock(td); + PROC_SUNLOCK(p); /* Do the same timestamp bookkeeping that mi_switch() would do. */ new_switchtime = cpu_ticks(); @@ -484,9 +487,8 @@ thread_exit(void) td->td_ru.ru_nvcsw++; ruxagg(p, td); rucollect(&p->p_ru, &td->td_ru); + PROC_STATUNLOCK(p); - thread_lock(td); - PROC_SUNLOCK(p); td->td_state = TDS_INACTIVE; #ifdef WITNESS witness_thread_exit(td); diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index e8430e4b602d..1ee80f051578 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -276,10 +276,10 @@ get_process_cputime(struct proc *targetp, struct timespec *ats) uint64_t runtime; struct rusage ru; - PROC_SLOCK(targetp); + PROC_STATLOCK(targetp); rufetch(targetp, &ru); runtime = targetp->p_rux.rux_runtime; - PROC_SUNLOCK(targetp); + PROC_STATUNLOCK(targetp); cputick2timespec(runtime, ats); } @@ -328,17 +328,17 @@ kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) break; case CLOCK_VIRTUAL: PROC_LOCK(p); - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &user, &sys); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); PROC_UNLOCK(p); TIMEVAL_TO_TIMESPEC(&user, ats); break; case CLOCK_PROF: PROC_LOCK(p); - PROC_SLOCK(p); + PROC_STATLOCK(p); calcru(p, &user, &sys); - PROC_SUNLOCK(p); + PROC_STATUNLOCK(p); PROC_UNLOCK(p); timevaladd(&user, &sys); TIMEVAL_TO_TIMESPEC(&user, ats); @@ -698,9 +698,9 @@ kern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) timevalsub(&aitv->it_value, &ctv); } } else { - PROC_SLOCK(p); + PROC_ITIMLOCK(p); *aitv = p->p_stats->p_timer[which]; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } return (0); } @@ -782,10 +782,10 @@ kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, aitv->it_value.tv_usec != 0 && aitv->it_value.tv_usec < tick) aitv->it_value.tv_usec = tick; - PROC_SLOCK(p); + PROC_ITIMLOCK(p); *oitv = p->p_stats->p_timer[which]; p->p_stats->p_timer[which] = *aitv; - PROC_SUNLOCK(p); + PROC_ITIMUNLOCK(p); } return (0); } diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 7fbe359cbaf1..33cf6e7f10c5 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -5031,3 +5033,18 @@ bus_free_resource(device_t dev, int type, struct resource *r) return (0); return (bus_release_resource(dev, type, rman_get_rid(r), r)); } + +int +device_getenv_int(device_t dev, const char *knob, int *iptr) +{ + char env[128]; + int sz; + + sz = snprintf(env, sizeof(env), "hw.%s.%d.%s", device_get_name(dev), device_get_unit(dev), knob); + if (sz >= sizeof(env)) { + /* XXX: log? return error? bump sysctl error? */ + log(LOG_ERR, "device_getenv_int: knob too long: '%s'", knob); + return 0; + } + return (getenv_int(env, iptr)); +} diff --git a/sys/kern/subr_prof.c b/sys/kern/subr_prof.c index cedfc1b3d1db..3d87ff92052c 100644 --- a/sys/kern/subr_prof.c +++ b/sys/kern/subr_prof.c @@ -421,12 +421,12 @@ sys_profil(struct thread *td, struct profil_args *uap) } PROC_LOCK(p); upp = &td->td_proc->p_stats->p_prof; - PROC_SLOCK(p); + PROC_PROFLOCK(p); upp->pr_off = uap->offset; upp->pr_scale = uap->scale; upp->pr_base = uap->samples; upp->pr_size = uap->size; - PROC_SUNLOCK(p); + PROC_PROFUNLOCK(p); startprofclock(p); PROC_UNLOCK(p); @@ -466,15 +466,15 @@ addupc_intr(struct thread *td, uintfptr_t pc, u_int ticks) if (ticks == 0) return; prof = &td->td_proc->p_stats->p_prof; - PROC_SLOCK(td->td_proc); + PROC_PROFLOCK(td->td_proc); if (pc < prof->pr_off || (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size) { - PROC_SUNLOCK(td->td_proc); + PROC_PROFUNLOCK(td->td_proc); return; /* out of range; ignore */ } addr = prof->pr_base + i; - PROC_SUNLOCK(td->td_proc); + PROC_PROFUNLOCK(td->td_proc); if ((v = fuswintr(addr)) == -1 || suswintr(addr, v + ticks) == -1) { td->td_profil_addr = pc; td->td_profil_ticks = ticks; @@ -509,15 +509,15 @@ addupc_task(struct thread *td, uintfptr_t pc, u_int ticks) } p->p_profthreads++; prof = &p->p_stats->p_prof; - PROC_SLOCK(p); + PROC_PROFLOCK(p); if (pc < prof->pr_off || (i = PC_TO_INDEX(pc, prof)) >= prof->pr_size) { - PROC_SUNLOCK(p); + PROC_PROFUNLOCK(p); goto out; } addr = prof->pr_base + i; - PROC_SUNLOCK(p); + PROC_PROFUNLOCK(p); PROC_UNLOCK(p); if (copyin(addr, &v, sizeof(v)) == 0) { v += ticks; diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 01996155e4cc..8dddc9b556f6 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -75,6 +75,20 @@ __FBSDID("$FreeBSD$"); #include +/* + * The following macro defines how many bytes will be allocated from + * the stack instead of memory allocated when passing the IOCTL data + * structures from userspace and to the kernel. Some IOCTLs having + * small data structures are used very frequently and this small + * buffer on the stack gives a significant speedup improvement for + * those requests. The value of this define should be greater or equal + * to 64 bytes and should also be power of two. The data structure is + * currently hard-aligned to a 8-byte boundary on the stack. This + * should currently be sufficient for all supported platforms. + */ +#define SYS_IOCTL_SMALL_SIZE 128 /* bytes */ +#define SYS_IOCTL_SMALL_ALIGN 8 /* bytes */ + int iosize_max_clamp = 0; SYSCTL_INT(_debug, OID_AUTO, iosize_max_clamp, CTLFLAG_RW, &iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX"); @@ -646,10 +660,7 @@ struct ioctl_args { int sys_ioctl(struct thread *td, struct ioctl_args *uap) { -#ifndef SYS_IOCTL_SMALL_SIZE -#define SYS_IOCTL_SMALL_SIZE 128 -#endif - u_char smalldata[SYS_IOCTL_SMALL_SIZE] __aligned(8); + u_char smalldata[SYS_IOCTL_SMALL_SIZE] __aligned(SYS_IOCTL_SMALL_ALIGN); u_long com; int arg, error; u_int size; diff --git a/sys/mips/conf/WZR-HPAG300H b/sys/mips/conf/WZR-HPAG300H new file mode 100644 index 000000000000..21e9bccfa469 --- /dev/null +++ b/sys/mips/conf/WZR-HPAG300H @@ -0,0 +1,49 @@ +# +# Specific board setup for the Buffalo Airstation WZR-HPAG300H +# +# The WZR-HPAG300H has the following hardware: +# +# + AR7161 CPU SoC +# + 2x AR9280 5GHz 11n +# + AR8136 Gigabit switch +# + 2 m25ll128(really w25q128) based 16MB flash +# + 128MB RAM +# + uboot environment + +# $FreeBSD$ + +include "AR71XX_BASE" +ident "WZR-HPAG300H" +hints "WZR-HPAG300H.hints" + +options AR71XX_REALMEM=128*1024*1024 + +options AR71XX_ENV_UBOOT + +options BOOTVERBOSE + +# GEOM modules +device geom_uncompress # compressed in-memory filesystem hackery! +device geom_map # to get access to the SPI flash partitions + +options ROOTDEVNAME=\"ufs:/dev/map/rootfs.uncompress\" + +options AR71XX_ATH_EEPROM # Fetch EEPROM/PCI config from flash +options ATH_EEPROM_FIRMWARE # Use EEPROM from flash +device firmware # Used by the above + +# Options required for miiproxy and mdiobus +options ARGE_MDIO # Export an MDIO bus separate from arge +device miiproxy # MDIO bus <-> MII PHY rendezvous + +device etherswitch +device arswitch + +# hwpmc +device hwpmc_mips24k +device hwpmc + +# load these via modules, shrink kernel +nodevice if_bridge +nodevice bridgestp +nodevice random diff --git a/sys/mips/conf/WZR-HPAG300H.hints b/sys/mips/conf/WZR-HPAG300H.hints new file mode 100644 index 000000000000..b314b2f7b214 --- /dev/null +++ b/sys/mips/conf/WZR-HPAG300H.hints @@ -0,0 +1,132 @@ +# $FreeBSD$ + +# arge0 is connected to the LAN side of the switch PHY. +# arge1 is connected to the single port WAN side of the switch PHY. + +# arge1 MDIO bus +hint.argemdio.0.at="nexus0" +hint.argemdio.0.maddr=0x1a000000 +hint.argemdio.0.msize=0x1000 +hint.argemdio.0.order=0 + +hint.arge.0.phymask=0x0 +hint.arge.0.media=1000 +hint.arge.0.fduplex=1 +hint.arge.0.eeprommac=0x1f05120c +hint.arge.0.mdio=mdioproxy0 # .. off of the switch mdiobus +hint.arge.0.miimode=3 + +hint.arge.1.phymask=0x10 +hint.arge.1.media=1000 +hint.arge.1.fduplex=1 +hint.arge.1.eeprommac=0x1f05520c +hint.arge.1.mdio=mdioproxy0 # .. off of the switch mdiobus +hint.arge.1.miimode=3 +# +# AR7240 switch config +# +hint.arswitch.0.at="mdio0" +hint.arswitch.0.is_7240=0 # We need to be explicitly told this +hint.arswitch.0.numphys=4 # 5 active switch PHYs (PHY 0 -> 4) +hint.arswitch.0.phy4cpu=0 # No, PHY 4 == dedicated PHY +hint.arswitch.0.is_rgmii=1 # Yes, is RGMII +hint.arswitch.0.is_gmii=0 # No, not GMII + +# ath0 - slot 17 +hint.pcib.0.bus.0.17.0.ath_fixup_addr=0x1f051000 +hint.pcib.0.bus.0.17.0.ath_fixup_size=4096 + +# ath1 - slot 18 +hint.pcib.0.bus.0.18.0.ath_fixup_addr=0x1f055000 +hint.pcib.0.bus.0.18.0.ath_fixup_size=4096 +# .. and now, telling each ath(4) NIC where to find the firmware +# image. +hint.ath.0.eeprom_firmware="pcib.0.bus.0.17.0.eeprom_firmware" +hint.ath.1.eeprom_firmware="pcib.0.bus.0.18.0.eeprom_firmware" + +# Inherited from AR71XX_BASE.hints +#hint.mx25l.0.at="spibus0" +#hint.mx25l.0.cs=0 +# This board has two 16 MB flash devices on difference Chip Select pins +hint.mx25l.1.at="spibus0" +hint.mx25l.1.cs=1 + + +# Geom MAP + +hint.map.0.at="flash/spi0" +hint.map.0.start=0x00000000 +hint.map.0.end=0x00040000 +hint.map.0.name="uboot" +hint.map.0.readonly=1 + +hint.map.1.at="flash/spi0" +hint.map.1.start=0x00040000 +hint.map.1.end=0x00050000 +hint.map.1.name="u-boot-env" +hint.map.1.readonly=1 + +hint.map.2.at="flash/spi0" +hint.map.2.start=0x00050000 +hint.map.2.end=0x00060000 +hint.map.2.name="ART" +hint.map.2.readonly=1 + +# requires a 1M alignment and padding in the image. +# make sure you are using conv=sync and bs=1M in your dd +hint.map.3.at="flash/spi0" +hint.map.3.start=0x00060000 +hint.map.3.end="search:0x00160000:0x100000:.!/bin/sh" +hint.map.3.name="kernel" +hint.map.3.readonly=1 + +hint.map.4.at="flash/spi0" +hint.map.4.start="search:0x00160000:0x100000:.!/bin/sh" +hint.map.4.end=0x01000000 +hint.map.4.name="rootfs" +hint.map.4.readonly=1 + +hint.map.5.at="flash/spi1" +hint.map.5.start=0x00FF0000 +hint.map.5.end=0x01000000 +hint.map.5.name="cfg" +hint.map.5.readonly=0 + +# Pin 1 - SCK +# Pin 2 - SDA +# Pin 3 - usb +# Pin 4 - +# Pin 5 - aoss +# Pin 6 - router auto +# Pin 7 - router off +# Pin 8 - movie engine +# Pin 9 - +# Pin 10 - +# Pin 11 - reset button +# Pin 12 - CS0 +# Pin 13 - CS1 +# Pin 14 - +# Pin 15 - +# Pin 16 - +# Pin 17 - + +# Don't flip on anything that isn't already enabled. +# Force on CS lines for flash devices, apparently this isn't done +# by uboot in normal booting. No idea why. +hint.gpio.0.function_set=0x00003004 +hint.gpio.0.function_clear=0x00000000 + +# These are the GPIO LEDs and buttons which can be software controlled. +hint.gpio.0.pinmask=0x0001 + +hint.gpio.0.pinon=0x00000004 + +hint.gpioiic.0.at="gpiobus0" +#hint.gpioiic.0.pins=0x0003 +hint.gpioiic.0.sda=0 +hint.gpioiic.0.scl=1 + +# LEDs are configured separately and driven by the LED device +hint.gpioled.0.at="gpiobus0" +hint.gpioled.0.name="red-diag" +hint.gpioled.0.pins=0x0001 diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index 617f9ee13d88..46fbf5b6232d 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -103,8 +103,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, u_int8_t atype, adst; int loop_copy = 0; int isphds; -#if defined(INET) || defined(INET6) - struct llentry *lle; +#ifdef INET + int is_gw; #endif if (!((ifp->if_flags & IFF_UP) && @@ -125,8 +125,11 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, else if (ifp->if_flags & IFF_NOARP) adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; else { - error = arpresolve(ifp, ro ? ro->ro_rt : NULL, - m, dst, &adst, &lle); + is_gw = 0; + if (ro != NULL && ro->ro_rt != NULL && + (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; + error = arpresolve(ifp, is_gw, m, dst, &adst, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -164,7 +167,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle); + error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, NULL); if (error) return (error); atype = ARCTYPE_INET6; diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index b96f43854fa2..9ba1f636063f 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -147,18 +147,25 @@ ether_output(struct ifnet *ifp, struct mbuf *m, { short type; int error = 0, hdrcmplt = 0; - u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN]; + u_char edst[ETHER_ADDR_LEN]; struct llentry *lle = NULL; struct rtentry *rt0 = NULL; struct ether_header *eh; struct pf_mtag *t; int loop_copy = 1; int hlen; /* link layer header length */ + int is_gw = 0; + uint32_t pflags = 0; if (ro != NULL) { - if (!(m->m_flags & (M_BCAST | M_MCAST))) + if (!(m->m_flags & (M_BCAST | M_MCAST))) { lle = ro->ro_lle; + if (lle != NULL) + pflags = lle->la_flags; + } rt0 = ro->ro_rt; + if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; } #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -177,10 +184,10 @@ ether_output(struct ifnet *ifp, struct mbuf *m, switch (dst->sa_family) { #ifdef INET case AF_INET: - if (lle != NULL && (lle->la_flags & LLE_VALID)) + if (lle != NULL && (pflags & LLE_VALID) != 0) memcpy(edst, &lle->ll_addr.mac16, sizeof(edst)); else - error = arpresolve(ifp, rt0, m, dst, edst, &lle); + error = arpresolve(ifp, is_gw, m, dst, edst, &pflags); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -215,10 +222,11 @@ ether_output(struct ifnet *ifp, struct mbuf *m, #endif #ifdef INET6 case AF_INET6: - if (lle != NULL && (lle->la_flags & LLE_VALID)) + if (lle != NULL && (pflags & LLE_VALID)) memcpy(edst, &lle->ll_addr.mac16, sizeof(edst)); else - error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle); + error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, + &pflags); if (error) return error; type = htons(ETHERTYPE_IPV6); @@ -227,10 +235,8 @@ ether_output(struct ifnet *ifp, struct mbuf *m, case pseudo_AF_HDRCMPLT: { const struct ether_header *eh; - + hdrcmplt = 1; - eh = (const struct ether_header *)dst->sa_data; - (void)memcpy(esrc, eh->ether_shost, sizeof (esrc)); /* FALLTHROUGH */ case AF_UNSPEC: @@ -245,7 +251,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m, senderr(EAFNOSUPPORT); } - if (lle != NULL && (lle->la_flags & LLE_IFADDR)) { + if ((pflags & LLE_IFADDR) != 0) { update_mbuf_csumflags(m, m); return (if_simloop(ifp, m, dst->sa_family, 0)); } @@ -258,15 +264,11 @@ ether_output(struct ifnet *ifp, struct mbuf *m, if (m == NULL) senderr(ENOBUFS); eh = mtod(m, struct ether_header *); - (void)memcpy(&eh->ether_type, &type, - sizeof(eh->ether_type)); - (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); - if (hdrcmplt) - (void)memcpy(eh->ether_shost, esrc, - sizeof(eh->ether_shost)); - else - (void)memcpy(eh->ether_shost, IF_LLADDR(ifp), - sizeof(eh->ether_shost)); + if (hdrcmplt == 0) { + memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); + memcpy(eh->ether_dhost, edst, sizeof (edst)); + memcpy(eh->ether_shost, IF_LLADDR(ifp),sizeof(eh->ether_shost)); + } /* * If a simplex interface, and the packet is being sent to our diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index da54ebf69fdf..9066c0d3cd63 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -101,8 +101,8 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, int loop_copy = 0, error = 0, hdrcmplt = 0; u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN]; struct fddi_header *fh; -#if defined(INET) || defined(INET6) - struct llentry *lle; +#ifdef INET + int is_gw; #endif #ifdef MAC @@ -121,11 +121,11 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, switch (dst->sa_family) { #ifdef INET case AF_INET: { - struct rtentry *rt0 = NULL; - - if (ro != NULL) - rt0 = ro->ro_rt; - error = arpresolve(ifp, rt0, m, dst, edst, &lle); + is_gw = 0; + if (ro != NULL && ro->ro_rt != NULL && + (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; + error = arpresolve(ifp, is_gw, m, dst, edst, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -161,7 +161,7 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle); + error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL); if (error) return (error); /* Something bad happened */ type = htons(ETHERTYPE_IPV6); diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c index 39e9cf9fd867..5bb12f9ee3aa 100644 --- a/sys/net/if_fwsubr.c +++ b/sys/net/if_fwsubr.c @@ -89,8 +89,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct mbuf *mtail; int unicast, dgl, foff; static int next_dgl; -#if defined(INET) || defined(INET6) - struct llentry *lle; +#ifdef INET + int is_gw; #endif #ifdef MAC @@ -140,7 +140,11 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, * doesn't fit into the arp model. */ if (unicast) { - error = arpresolve(ifp, ro ? ro->ro_rt : NULL, m, dst, (u_char *) destfw, &lle); + is_gw = 0; + if (ro != NULL && ro->ro_rt != NULL && + (ro->ro_rt->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; + error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -170,7 +174,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, case AF_INET6: if (unicast) { error = nd6_storelladdr(fc->fc_ifp, m, dst, - (u_char *) destfw, &lle); + (u_char *) destfw, NULL); if (error) return (error); } diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index 8e55e8b87697..727df37f70db 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -212,12 +212,13 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct iso88025_header gen_th; struct sockaddr_dl *sdl = NULL; struct rtentry *rt0 = NULL; -#if defined(INET) || defined(INET6) - struct llentry *lle; -#endif + int is_gw = 0; - if (ro != NULL) + if (ro != NULL) { rt0 = ro->ro_rt; + if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; + } #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -257,7 +258,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, switch (dst->sa_family) { #ifdef INET case AF_INET: - error = arpresolve(ifp, rt0, m, dst, edst, &lle); + error = arpresolve(ifp, is_gw, m, dst, edst, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); snap_type = ETHERTYPE_IP; @@ -292,7 +293,7 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle); + error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL); if (error) return (error); snap_type = ETHERTYPE_IPV6; diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index d5d9798e56dd..f1d06562c7b7 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -286,19 +286,20 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip, * Resolve an IP address into an ethernet address. * On input: * ifp is the interface we use - * rt0 is the route to the final destination (possibly useless) + * is_gw != if @dst represents gateway to some destination * m is the mbuf. May be NULL if we don't have a packet. * dst is the next hop, * desten is where we want the address. + * flags returns lle entry flags. * - * On success, desten is filled in and the function returns 0; + * On success, desten and flags are filled in and the function returns 0; * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. * Note that m_freem() handles NULL. */ int -arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, - const struct sockaddr *dst, u_char *desten, struct llentry **lle) +arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, + const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { struct llentry *la = 0; u_int flags = 0; @@ -306,7 +307,9 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, struct mbuf *next = NULL; int error, renew; - *lle = NULL; + if (pflags != NULL) + *pflags = 0; + if (m != NULL) { if (m->m_flags & M_BCAST) { /* broadcast */ @@ -354,7 +357,8 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, la->la_preempt--; } - *lle = la; + if (pflags != NULL) + *pflags = la->la_flags; error = 0; goto done; } @@ -412,8 +416,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, if (la->la_asked < V_arp_maxtries) error = EWOULDBLOCK; /* First request. */ else - error = rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) ? - EHOSTUNREACH : EHOSTDOWN; + error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN; if (renew) { int canceled; diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index fbd0a1ac4e9e..39fc3868dc3c 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -112,11 +112,10 @@ struct sockaddr_inarp { extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN]; extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN]; -struct llentry; struct ifaddr; -int arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, - const struct sockaddr *dst, u_char *desten, struct llentry **lle); +int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, + const struct sockaddr *dst, u_char *desten, uint32_t *pflags); void arprequest(struct ifnet *, const struct in_addr *, const struct in_addr *, u_char *); void arp_ifinit(struct ifnet *, struct ifaddr *); diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c index 1ab6c73c1ddb..1021475f9319 100644 --- a/sys/netinet/toecore.c +++ b/sys/netinet/toecore.c @@ -516,15 +516,12 @@ int toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr, uint16_t *vtag) { -#ifdef INET - struct llentry *lle; -#endif int rc; switch (sa->sa_family) { #ifdef INET case AF_INET: - rc = arpresolve(ifp, NULL, NULL, sa, lladdr, &lle); + rc = arpresolve(ifp, 0, NULL, sa, lladdr, NULL); break; #endif #ifdef INET6 diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index cedf6e2b873c..5e1f25ff3236 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -2206,9 +2206,6 @@ nd6_need_cache(struct ifnet *ifp) case IFT_IEEE80211: #endif case IFT_INFINIBAND: - case IFT_GIF: /* XXX need more cases? */ - case IFT_PPP: - case IFT_TUNNEL: case IFT_BRIDGE: case IFT_PROPVIRTUAL: return (1); @@ -2235,6 +2232,8 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia) struct llentry *ln; ifp = ia->ia_ifa.ifa_ifp; + if (nd6_need_cache(ifp) == 0) + return (0); IF_AFDATA_LOCK(ifp); ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR | @@ -2279,11 +2278,12 @@ nd6_rem_ifa_lle(struct in6_ifaddr *ia) */ int nd6_storelladdr(struct ifnet *ifp, struct mbuf *m, - const struct sockaddr *dst, u_char *desten, struct llentry **lle) + const struct sockaddr *dst, u_char *desten, uint32_t *pflags) { struct llentry *ln; - *lle = NULL; + if (pflags != NULL) + *pflags = 0; IF_AFDATA_UNLOCK_ASSERT(ifp); if (m != NULL && m->m_flags & M_MCAST) { int i; @@ -2335,7 +2335,8 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m, } bcopy(&ln->ll_addr, desten, ifp->if_addrlen); - *lle = ln; + if (pflags != NULL) + *pflags = ln->la_flags; LLE_RUNLOCK(ln); /* * A *small* use after free race exists here diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 358f4ecb167a..17db6183320d 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -418,7 +418,7 @@ int nd6_need_cache(struct ifnet *); int nd6_add_ifa_lle(struct in6_ifaddr *); void nd6_rem_ifa_lle(struct in6_ifaddr *); int nd6_storelladdr(struct ifnet *, struct mbuf *, - const struct sockaddr *, u_char *, struct llentry **); + const struct sockaddr *, u_char *, uint32_t *); /* nd6_nbr.c */ void nd6_na_input(struct mbuf *, int, int); diff --git a/sys/netipsec/ipip_var.h b/sys/netipsec/ipip_var.h deleted file mode 100644 index 02420c192e26..000000000000 --- a/sys/netipsec/ipip_var.h +++ /dev/null @@ -1,71 +0,0 @@ -/* $FreeBSD$ */ -/* $OpenBSD: ip_ipip.h,v 1.5 2002/06/09 16:26:10 itojun Exp $ */ -/*- - * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). - * - * The original version of this code was written by John Ioannidis - * for BSD/OS in Athens, Greece, in November 1995. - * - * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, - * by Angelos D. Keromytis. - * - * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis - * and Niels Provos. - * - * Additional features in 1999 by Angelos D. Keromytis. - * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, - * Angelos D. Keromytis and Niels Provos. - * Copyright (c) 2001, Angelos D. Keromytis. - * - * Permission to use, copy, and modify this software with or without fee - * is hereby granted, provided that this entire notice is included in - * all copies of any software which is or includes a copy or - * modification of this software. - * You may use this code under the GNU public license if you so wish. Please - * contribute changes back to the authors under this freer than GPL license - * so that we may further the use of strong encryption without limitations to - * all. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE - * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR - * PURPOSE. - */ - -#ifndef _NETINET_IPIP_H_ -#define _NETINET_IPIP_H_ - -/* - * IP-inside-IP processing. - * Not quite all the functionality of RFC-1853, but the main idea is there. - */ - -struct ipipstat { - uint64_t ipips_ipackets; /* total input packets */ - uint64_t ipips_opackets; /* total output packets */ - uint64_t ipips_hdrops; /* packet shorter than header shows */ - uint64_t ipips_qfull; - uint64_t ipips_ibytes; - uint64_t ipips_obytes; - uint64_t ipips_pdrops; /* packet dropped due to policy */ - uint64_t ipips_spoof; /* IP spoofing attempts */ - uint64_t ipips_family; /* Protocol family mismatch */ - uint64_t ipips_unspec; /* Missing tunnel endpoint address */ -}; - -#ifdef _KERNEL -#include - -VNET_DECLARE(int, ipip_allow); -VNET_PCPUSTAT_DECLARE(struct ipipstat, ipipstat); - -#define IPIPSTAT_ADD(name, val) \ - VNET_PCPUSTAT_ADD(struct ipipstat, ipipstat, name, (val)) -#define IPIPSTAT_INC(name) IPIPSTAT_ADD(name, 1) -#define V_ipip_allow VNET(ipip_allow) -#endif /* _KERNEL */ -#endif /* _NETINET_IPIP_H_ */ diff --git a/sys/netipsec/xform.h b/sys/netipsec/xform.h index 62e8ca5dbdec..a6bce34a7a2f 100644 --- a/sys/netipsec/xform.h +++ b/sys/netipsec/xform.h @@ -109,8 +109,6 @@ extern int xform_init(struct secasvar *sav, int xftype); struct cryptoini; /* XF_IP4 */ -extern int ip4_input6(struct mbuf **m, int *offp, int proto); -extern int ip4_input(struct mbuf **, int *, int); extern int ipip_output(struct mbuf *, struct ipsecrequest *, struct mbuf **, int, int); diff --git a/sys/netipsec/xform_ipip.c b/sys/netipsec/xform_ipip.c index 591c44f92972..67b86edbcd56 100644 --- a/sys/netipsec/xform_ipip.c +++ b/sys/netipsec/xform_ipip.c @@ -64,290 +64,24 @@ #include #include #include -#include #include #include -#include - #ifdef INET6 #include #include #include #include -#include +#include #endif #include #include -#include - -/* - * We can control the acceptance of IP4 packets by altering the sysctl - * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. - */ -VNET_DEFINE(int, ipip_allow) = 0; -VNET_PCPUSTAT_DEFINE(struct ipipstat, ipipstat); -VNET_PCPUSTAT_SYSINIT(ipipstat); - -#ifdef VIMAGE -VNET_PCPUSTAT_SYSUNINIT(ipipstat); -#endif /* VIMAGE */ - -SYSCTL_DECL(_net_inet_ipip); -SYSCTL_INT(_net_inet_ipip, OID_AUTO, ipip_allow, CTLFLAG_VNET | CTLFLAG_RW, - &VNET_NAME(ipip_allow), 0, ""); -SYSCTL_VNET_PCPUSTAT(_net_inet_ipip, IPSECCTL_STATS, stats, - struct ipipstat, ipipstat, - "IPIP statistics (struct ipipstat, netipsec/ipip_var.h)"); - -/* XXX IPCOMP */ -#define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) - -static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); - -#ifdef INET6 -/* - * Really only a wrapper for ipip_input(), for use with IPv6. - */ int -ip4_input6(struct mbuf **m, int *offp, int proto) -{ -#if 0 - /* If we do not accept IP-in-IP explicitly, drop. */ - if (!V_ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { - DPRINTF(("%s: dropped due to policy\n", __func__)); - IPIPSTAT_INC(ipips_pdrops); - m_freem(*m); - return IPPROTO_DONE; - } -#endif - _ipip_input(*m, *offp, NULL); - return IPPROTO_DONE; -} -#endif /* INET6 */ - -#ifdef INET -/* - * Really only a wrapper for ipip_input(), for use with IPv4. - */ -int -ip4_input(struct mbuf **mp, int *offp, int proto) -{ -#if 0 - /* If we do not accept IP-in-IP explicitly, drop. */ - if (!V_ipip_allow && (m->m_flags & M_IPSEC) == 0) { - DPRINTF(("%s: dropped due to policy\n", __func__)); - IPIPSTAT_INC(ipips_pdrops); - m_freem(m); - return; - } -#endif - _ipip_input(*mp, *offp, NULL); - return (IPPROTO_DONE); -} -#endif /* INET */ - -/* - * ipip_input gets called when we receive an IP{46} encapsulated packet, - * either because we got it at a real interface, or because AH or ESP - * were being used in tunnel mode (in which case the rcvif element will - * contain the address of the encX interface associated with the tunnel. - */ - -static void -_ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) -{ - struct ip *ipo; -#ifdef INET6 - struct ip6_hdr *ip6 = NULL; - u_int8_t itos; -#endif - int isr; - u_int8_t otos; - u_int8_t v; - int hlen; - - IPIPSTAT_INC(ipips_ipackets); - - m_copydata(m, 0, 1, &v); - - switch (v >> 4) { -#ifdef INET - case 4: - hlen = sizeof(struct ip); - break; -#endif /* INET */ -#ifdef INET6 - case 6: - hlen = sizeof(struct ip6_hdr); - break; -#endif - default: - IPIPSTAT_INC(ipips_family); - m_freem(m); - return /* EAFNOSUPPORT */; - } - - /* Bring the IP header in the first mbuf, if not there already */ - if (m->m_len < hlen) { - if ((m = m_pullup(m, hlen)) == NULL) { - DPRINTF(("%s: m_pullup (1) failed\n", __func__)); - IPIPSTAT_INC(ipips_hdrops); - return; - } - } - ipo = mtod(m, struct ip *); - - /* Keep outer ecn field. */ - switch (v >> 4) { -#ifdef INET - case 4: - otos = ipo->ip_tos; - break; -#endif /* INET */ -#ifdef INET6 - case 6: - otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; - break; -#endif - default: - panic("ipip_input: unknown ip version %u (outer)", v>>4); - } - - /* Remove outer IP header */ - m_adj(m, iphlen); - - /* Sanity check */ - if (m->m_pkthdr.len < sizeof(struct ip)) { - IPIPSTAT_INC(ipips_hdrops); - m_freem(m); - return; - } - - m_copydata(m, 0, 1, &v); - - switch (v >> 4) { -#ifdef INET - case 4: - hlen = sizeof(struct ip); - break; -#endif /* INET */ - -#ifdef INET6 - case 6: - hlen = sizeof(struct ip6_hdr); - break; -#endif - default: - IPIPSTAT_INC(ipips_family); - m_freem(m); - return; /* EAFNOSUPPORT */ - } - - /* - * Bring the inner IP header in the first mbuf, if not there already. - */ - if (m->m_len < hlen) { - if ((m = m_pullup(m, hlen)) == NULL) { - DPRINTF(("%s: m_pullup (2) failed\n", __func__)); - IPIPSTAT_INC(ipips_hdrops); - return; - } - } - - /* - * RFC 1853 specifies that the inner TTL should not be touched on - * decapsulation. There's no reason this comment should be here, but - * this is as good as any a position. - */ - - /* Some sanity checks in the inner IP header */ - switch (v >> 4) { -#ifdef INET - case 4: - ipo = mtod(m, struct ip *); - ip_ecn_egress(V_ip4_ipsec_ecn, &otos, &ipo->ip_tos); - break; -#endif /* INET */ -#ifdef INET6 - case 6: - ip6 = (struct ip6_hdr *) ipo; - itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; - ip_ecn_egress(V_ip6_ipsec_ecn, &otos, &itos); - ip6->ip6_flow &= ~htonl(0xff << 20); - ip6->ip6_flow |= htonl((u_int32_t) itos << 20); - break; -#endif - default: - panic("ipip_input: unknown ip version %u (inner)", v>>4); - } - - /* Check for local address spoofing. */ - if ((m->m_pkthdr.rcvif == NULL || - !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && - V_ipip_allow != 2) { -#ifdef INET - if ((v >> 4) == IPVERSION && - in_localip(ipo->ip_src) != 0) { - IPIPSTAT_INC(ipips_spoof); - m_freem(m); - return; - } -#endif -#ifdef INET6 - if ((v & IPV6_VERSION_MASK) == IPV6_VERSION && - in6_localip(&ip6->ip6_src) != 0) { - IPIPSTAT_INC(ipips_spoof); - m_freem(m); - return; - } -#endif - } - - /* Statistics */ - IPIPSTAT_ADD(ipips_ibytes, m->m_pkthdr.len - iphlen); - - /* - * Interface pointer stays the same; if no IPsec processing has - * been done (or will be done), this will point to a normal - * interface. Otherwise, it'll point to an enc interface, which - * will allow a packet filter to distinguish between secure and - * untrusted packets. - */ - - switch (v >> 4) { -#ifdef INET - case 4: - isr = NETISR_IP; - break; -#endif -#ifdef INET6 - case 6: - isr = NETISR_IPV6; - break; -#endif - default: - panic("%s: bogus ip version %u", __func__, v>>4); - } - - if (netisr_queue(isr, m)) { /* (0) on success. */ - IPIPSTAT_INC(ipips_qfull); - DPRINTF(("%s: packet dropped because of full queue\n", - __func__)); - } -} - -int -ipip_output( - struct mbuf *m, - struct ipsecrequest *isr, - struct mbuf **mp, - int skip, - int protoff -) +ipip_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp, + int skip, int protoff) { struct secasvar *sav; u_int8_t tp, otos; @@ -383,7 +117,6 @@ ipip_output( "address in SA %s/%08lx\n", __func__, ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); - IPIPSTAT_INC(ipips_unspec); error = EINVAL; goto bad; } @@ -391,7 +124,6 @@ ipip_output( M_PREPEND(m, sizeof(struct ip), M_NOWAIT); if (m == 0) { DPRINTF(("%s: M_PREPEND failed\n", __func__)); - IPIPSTAT_INC(ipips_hdrops); error = ENOBUFS; goto bad; } @@ -463,22 +195,17 @@ ipip_output( "address in SA %s/%08lx\n", __func__, ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); - IPIPSTAT_INC(ipips_unspec); error = ENOBUFS; goto bad; } /* scoped address handling */ ip6 = mtod(m, struct ip6_hdr *); - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) - ip6->ip6_src.s6_addr16[1] = 0; - if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) - ip6->ip6_dst.s6_addr16[1] = 0; - + in6_clearscope(&ip6->ip6_src); + in6_clearscope(&ip6->ip6_dst); M_PREPEND(m, sizeof(struct ip6_hdr), M_NOWAIT); if (m == 0) { DPRINTF(("%s: M_PREPEND failed\n", __func__)); - IPIPSTAT_INC(ipips_hdrops); error = ENOBUFS; goto bad; } @@ -532,39 +259,12 @@ ipip_output( nofamily: DPRINTF(("%s: unsupported protocol family %u\n", __func__, saidx->dst.sa.sa_family)); - IPIPSTAT_INC(ipips_family); error = EAFNOSUPPORT; /* XXX diffs from openbsd */ goto bad; } - IPIPSTAT_INC(ipips_opackets); *mp = m; - -#ifdef INET - if (saidx->dst.sa.sa_family == AF_INET) { -#if 0 - if (sav->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += - m->m_pkthdr.len - sizeof(struct ip); -#endif - IPIPSTAT_ADD(ipips_obytes, - m->m_pkthdr.len - sizeof(struct ip)); - } -#endif /* INET */ - -#ifdef INET6 - if (saidx->dst.sa.sa_family == AF_INET6) { -#if 0 - if (sav->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += - m->m_pkthdr.len - sizeof(struct ip6_hdr); -#endif - IPIPSTAT_ADD(ipips_obytes, - m->m_pkthdr.len - sizeof(struct ip6_hdr)); - } -#endif /* INET6 */ - - return 0; + return (0); bad: if (m) m_freem(m); @@ -572,8 +272,6 @@ ipip_output( return (error); } -#ifdef IPSEC -#if defined(INET) || defined(INET6) static int ipe4_init(struct secasvar *sav, struct xformsw *xsp) { @@ -603,63 +301,10 @@ static struct xformsw ipe4_xformsw = { ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, }; -extern struct domain inetdomain; -#endif /* INET || INET6 */ -#ifdef INET -static struct protosw ipe4_protosw = { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPV4, - .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, - .pr_input = ip4_input, - .pr_ctloutput = rip_ctloutput, - .pr_usrreqs = &rip_usrreqs -}; -#endif /* INET */ -#if defined(INET6) && defined(INET) -static struct protosw ipe6_protosw = { - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPV6, - .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, - .pr_input = ip4_input6, - .pr_ctloutput = rip_ctloutput, - .pr_usrreqs = &rip_usrreqs -}; -#endif /* INET6 && INET */ - -#ifdef INET -/* - * Check the encapsulated packet to see if we want it - */ -static int -ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg) -{ - /* - * Only take packets coming from IPSEC tunnels; the rest - * must be handled by the gif tunnel code. Note that we - * also return a minimum priority when we want the packet - * so any explicit gif tunnels take precedence. - */ - return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); -} -#endif /* INET */ - static void ipe4_attach(void) { xform_register(&ipe4_xformsw); - /* attach to encapsulation framework */ - /* XXX save return cookie for detach on module remove */ -#ifdef INET - (void) encap_attach_func(AF_INET, -1, - ipe4_encapcheck, &ipe4_protosw, NULL); -#endif -#if defined(INET6) && defined(INET) - (void) encap_attach_func(AF_INET6, -1, - ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL); -#endif } SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); -#endif /* IPSEC */ diff --git a/sys/ofed/drivers/infiniband/core/addr.c b/sys/ofed/drivers/infiniband/core/addr.c index f608244da9a5..c3d5b4fc0bf6 100644 --- a/sys/ofed/drivers/infiniband/core/addr.c +++ b/sys/ofed/drivers/infiniband/core/addr.c @@ -347,14 +347,12 @@ static int addr_resolve(struct sockaddr *src_in, struct sockaddr_in6 *sin6; struct ifaddr *ifa; struct ifnet *ifp; -#if defined(INET) || defined(INET6) - struct llentry *lle; -#endif struct rtentry *rte; in_port_t port; u_char edst[MAX_ADDR_LEN]; int multi; int bcast; + int is_gw = 0; int error = 0; /* @@ -430,6 +428,8 @@ static int addr_resolve(struct sockaddr *src_in, RTFREE_LOCKED(rte); return -EHOSTUNREACH; } + if (rte->rt_flags & RTF_GATEWAY) + is_gw = 1; /* * If it's not multicast or broadcast and the route doesn't match the * requested interface return unreachable. Otherwise fetch the @@ -467,12 +467,12 @@ static int addr_resolve(struct sockaddr *src_in, switch (dst_in->sa_family) { #ifdef INET case AF_INET: - error = arpresolve(ifp, rte, NULL, dst_in, edst, &lle); + error = arpresolve(ifp, is_gw, NULL, dst_in, edst, NULL); break; #endif #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst, &lle); + error = nd6_storelladdr(ifp, NULL, dst_in, (u_char *)edst,NULL); break; #endif default: diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index 5cd344187a8b..b3afc210c8e1 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1259,13 +1259,15 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, struct llentry *lle = NULL; struct rtentry *rt0 = NULL; struct ipoib_header *eh; - int error = 0; + int error = 0, is_gw = 0; short type; if (ro != NULL) { if (!(m->m_flags & (M_BCAST | M_MCAST))) lle = ro->ro_lle; rt0 = ro->ro_rt; + if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0) + is_gw = 1; } #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -1292,7 +1294,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, else if (m->m_flags & M_MCAST) ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst); else - error = arpresolve(ifp, rt0, m, dst, edst, &lle); + error = arpresolve(ifp, is_gw, m, dst, edst, NULL); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -1330,7 +1332,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m, else if (m->m_flags & M_MCAST) ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst); else - error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle); + error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, NULL); if (error) return error; type = htons(ETHERTYPE_IPV6); diff --git a/sys/powerpc/include/asm.h b/sys/powerpc/include/asm.h index 6b0ec1acfb1d..e571316d15ea 100644 --- a/sys/powerpc/include/asm.h +++ b/sys/powerpc/include/asm.h @@ -37,7 +37,7 @@ #include -#if defined(__PIC__) && !defined(__powerpc64__) +#if defined(PIC) && !defined(__powerpc64__) #define PIC_PROLOGUE XXX #define PIC_EPILOGUE XXX #define PIC_PLT(x) x@plt diff --git a/sys/powerpc/include/profile.h b/sys/powerpc/include/profile.h index 5c578c48c8af..eb11fc96d38d 100644 --- a/sys/powerpc/include/profile.h +++ b/sys/powerpc/include/profile.h @@ -119,7 +119,7 @@ __asm( " .text \n" \ " blr \n"); #else -#ifdef __PIC__ +#ifdef PIC #define _PLT "@plt" #else #define _PLT diff --git a/sys/sparc64/include/asm.h b/sys/sparc64/include/asm.h index 8a9f3548517d..dea06c547f9e 100644 --- a/sys/sparc64/include/asm.h +++ b/sys/sparc64/include/asm.h @@ -41,7 +41,7 @@ #include -#ifdef __PIC__ +#ifdef PIC #define PIC_PROLOGUE(r1, r2) \ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), r1 ; \ rd %pc, r2 ; \ diff --git a/sys/sys/bus.h b/sys/sys/bus.h index b15a5568200b..95584c36afb7 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -449,6 +449,7 @@ const char *device_get_nameunit(device_t dev); void *device_get_softc(device_t dev); device_state_t device_get_state(device_t dev); int device_get_unit(device_t dev); +int device_getenv_int(device_t dev, const char *knob, int *iptr); struct sysctl_ctx_list *device_get_sysctl_ctx(device_t dev); struct sysctl_oid *device_get_sysctl_tree(device_t dev); int device_is_alive(device_t dev); /* did probe succeed? */ diff --git a/sys/sys/callout.h b/sys/sys/callout.h index 8b514409fc58..1096cb26ff92 100644 --- a/sys/sys/callout.h +++ b/sys/sys/callout.h @@ -81,16 +81,24 @@ void _callout_init_lock(struct callout *, struct lock_object *, int); int callout_reset_sbt_on(struct callout *, sbintime_t, sbintime_t, void (*)(void *), void *, int, int); #define callout_reset_sbt(c, sbt, pr, fn, arg, flags) \ - callout_reset_sbt_on((c), (sbt), (pr), (fn), (arg), (c)->c_cpu, flags) + callout_reset_sbt_on((c), (sbt), (pr), (fn), (arg), (c)->c_cpu, (flags)) #define callout_reset_sbt_curcpu(c, sbt, pr, fn, arg, flags) \ - callout_reset_sbt_on((c), (sbt), (pr), (fn), (arg), PCPU_GET(cpuid), flags) + callout_reset_sbt_on((c), (sbt), (pr), (fn), (arg), PCPU_GET(cpuid),\ + (flags)) #define callout_reset_on(c, to_ticks, fn, arg, cpu) \ - callout_reset_sbt_on((c), (tick_sbt * (to_ticks)), 0, (fn), (arg), \ + callout_reset_sbt_on((c), tick_sbt * (to_ticks), 0, (fn), (arg), \ (cpu), C_HARDCLOCK) #define callout_reset(c, on_tick, fn, arg) \ callout_reset_on((c), (on_tick), (fn), (arg), (c)->c_cpu) #define callout_reset_curcpu(c, on_tick, fn, arg) \ callout_reset_on((c), (on_tick), (fn), (arg), PCPU_GET(cpuid)) +#define callout_schedule_sbt_on(c, sbt, pr, cpu, flags) \ + callout_reset_sbt_on((c), (sbt), (pr), (c)->c_func, (c)->c_arg, \ + (cpu), (flags)) +#define callout_schedule_sbt(c, sbt, pr, flags) \ + callout_schedule_sbt_on((c), (sbt), (pr), (c)->c_cpu, (flags)) +#define callout_schedule_sbt_curcpu(c, sbt, pr, flags) \ + callout_schedule_sbt_on((c), (sbt), (pr), PCPU_GET(cpuid), (flags)) int callout_schedule(struct callout *, int); int callout_schedule_on(struct callout *, int, int); #define callout_schedule_curcpu(c, on_tick) \ diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index 23405eae601c..a846975a394f 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -349,7 +349,7 @@ enum pmc_ops { #define PMC_F_NEEDS_LOGFILE 0x00020000 /*needs log file */ #define PMC_F_ATTACH_DONE 0x00040000 /*attached at least once */ -#define PMC_CALLCHAIN_DEPTH_MAX 32 +#define PMC_CALLCHAIN_DEPTH_MAX 128 #define PMC_CC_F_USERSPACE 0x01 /*userspace callchain*/ @@ -605,7 +605,7 @@ struct pmc_op_getdyneventinfo { #define PMC_LOG_BUFFER_SIZE 4 #define PMC_NLOGBUFFERS 1024 #define PMC_NSAMPLES 1024 -#define PMC_CALLCHAIN_DEPTH 16 +#define PMC_CALLCHAIN_DEPTH 32 #define PMC_SYSCTL_NAME_PREFIX "kern." PMC_MODULE_NAME "." diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fac0915f005c..7fe59625a76b 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -148,6 +148,8 @@ struct pargs { * q - td_contested lock * r - p_peers lock * t - thread lock + * u - process stat lock + * w - process timer lock * x - created at fork, only changes during single threading in exec * y - created at first aio, doesn't change until exit or exec at which * point we are single-threaded and only curthread changes it @@ -183,14 +185,14 @@ struct turnstile; * userland asks for rusage info. Backwards compatibility prevents putting * this directly in the user-visible rusage struct. * - * Locking for p_rux: (cj) means (j) for p_rux and (c) for p_crux. + * Locking for p_rux: (cu) means (u) for p_rux and (c) for p_crux. * Locking for td_rux: (t) for all fields. */ struct rusage_ext { - uint64_t rux_runtime; /* (cj) Real time. */ - uint64_t rux_uticks; /* (cj) Statclock hits in user mode. */ - uint64_t rux_sticks; /* (cj) Statclock hits in sys mode. */ - uint64_t rux_iticks; /* (cj) Statclock hits in intr mode. */ + uint64_t rux_runtime; /* (cu) Real time. */ + uint64_t rux_uticks; /* (cu) Statclock hits in user mode. */ + uint64_t rux_sticks; /* (cu) Statclock hits in sys mode. */ + uint64_t rux_iticks; /* (cu) Statclock hits in intr mode. */ uint64_t rux_uu; /* (c) Previous user time in usec. */ uint64_t rux_su; /* (c) Previous sys time in usec. */ uint64_t rux_tu; /* (c) Previous total time in usec. */ @@ -512,6 +514,9 @@ struct proc { LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */ LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */ struct mtx p_mtx; /* (n) Lock for this struct. */ + struct mtx p_statmtx; /* Lock for the stats */ + struct mtx p_itimmtx; /* Lock for the virt/prof timers */ + struct mtx p_profmtx; /* Lock for the profiling */ struct ksiginfo *p_ksi; /* Locked by parent proc lock */ sigqueue_t p_sigqueue; /* (c) Sigs not delivered to a td. */ #define p_siglist p_sigqueue.sq_signals @@ -523,7 +528,7 @@ struct proc { u_int p_swtick; /* (c) Tick when swapped in or out. */ struct itimerval p_realtimer; /* (c) Alarm timer. */ struct rusage p_ru; /* (a) Exit information. */ - struct rusage_ext p_rux; /* (cj) Internal resource usage. */ + struct rusage_ext p_rux; /* (cu) Internal resource usage. */ struct rusage_ext p_crux; /* (c) Internal child resource usage. */ int p_profthreads; /* (c) Num threads in addupc_task. */ volatile int p_exitthreads; /* (j) Number of threads exiting */ @@ -609,6 +614,18 @@ struct proc { #define PROC_SUNLOCK(p) mtx_unlock_spin(&(p)->p_slock) #define PROC_SLOCK_ASSERT(p, type) mtx_assert(&(p)->p_slock, (type)) +#define PROC_STATLOCK(p) mtx_lock_spin(&(p)->p_statmtx) +#define PROC_STATUNLOCK(p) mtx_unlock_spin(&(p)->p_statmtx) +#define PROC_STATLOCK_ASSERT(p, type) mtx_assert(&(p)->p_statmtx, (type)) + +#define PROC_ITIMLOCK(p) mtx_lock_spin(&(p)->p_itimmtx) +#define PROC_ITIMUNLOCK(p) mtx_unlock_spin(&(p)->p_itimmtx) +#define PROC_ITIMLOCK_ASSERT(p, type) mtx_assert(&(p)->p_itimmtx, (type)) + +#define PROC_PROFLOCK(p) mtx_lock_spin(&(p)->p_profmtx) +#define PROC_PROFUNLOCK(p) mtx_unlock_spin(&(p)->p_profmtx) +#define PROC_PROFLOCK_ASSERT(p, type) mtx_assert(&(p)->p_profmtx, (type)) + /* These flags are kept in p_flag. */ #define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock. */ #define P_CONTROLT 0x00002 /* Has a controlling terminal. */ diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h index a24e89ada46c..a07fdf8d2427 100644 --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -47,21 +47,22 @@ * Locking key: * b - created at fork, never changes * c - locked by proc mtx - * j - locked by proc slock * k - only accessed by curthread + * w - locked by proc itim lock + * w2 - locked by proc prof lock */ struct pstats { #define pstat_startzero p_cru struct rusage p_cru; /* Stats for reaped children. */ - struct itimerval p_timer[3]; /* (j) Virtual-time timers. */ + struct itimerval p_timer[3]; /* (w) Virtual-time timers. */ #define pstat_endzero pstat_startcopy #define pstat_startcopy p_prof struct uprof { /* Profile arguments. */ - caddr_t pr_base; /* (c + j) Buffer base. */ - u_long pr_size; /* (c + j) Buffer size. */ - u_long pr_off; /* (c + j) PC offset. */ - u_long pr_scale; /* (c + j) PC scaling. */ + caddr_t pr_base; /* (c + w2) Buffer base. */ + u_long pr_size; /* (c + w2) Buffer size. */ + u_long pr_off; /* (c + w2) PC offset. */ + u_long pr_scale; /* (c + w2) PC scaling. */ } p_prof; #define pstat_endcopy p_start struct timeval p_start; /* (b) Starting time. */ diff --git a/tools/build/options/WITHOUT_CROSS_COMPILER b/tools/build/options/WITHOUT_CROSS_COMPILER index ab1bd235bb05..80420c5625eb 100644 --- a/tools/build/options/WITHOUT_CROSS_COMPILER +++ b/tools/build/options/WITHOUT_CROSS_COMPILER @@ -1,13 +1,13 @@ .\" $FreeBSD$ Set to not build any cross compiler in the cross-tools stage of buildworld. If you are compiling a different version of -.Fx +.Fx than what is installed on the system, you will need to provide an alternate compiler with XCC to ensure success. If you are compiling with an identical version of -.Fx +.Fx to the host, this option may be safely used. This option may also be safe when the host version of -.Fx +.Fx is close to the sources being built, but all bets are off if there have been any changes to the toolchain between the versions. diff --git a/tools/build/options/WITHOUT_INCLUDES b/tools/build/options/WITHOUT_INCLUDES index 8ccb2078d643..40f8ff5b1be9 100644 --- a/tools/build/options/WITHOUT_INCLUDES +++ b/tools/build/options/WITHOUT_INCLUDES @@ -1,8 +1,7 @@ .\" $FreeBSD$ Set to not install header files. -This option used to be spelled +This option used to be spelled .Va NO_INCS . .Bf -symbolic The option does not work for build targets. .Ef - diff --git a/tools/build/options/WITHOUT_RCS b/tools/build/options/WITHOUT_RCS index e21e0270d52d..b4f89e162321 100644 --- a/tools/build/options/WITHOUT_RCS +++ b/tools/build/options/WITHOUT_RCS @@ -1,6 +1,5 @@ .\" $FreeBSD$ Set to not build -.Xr rcs 1 -, -.Xr etcupdate 8 -, and related utilities. +.Xr rcs 1 , +.Xr etcupdate 8 , +and related utilities. diff --git a/tools/build/options/WITH_FMAKE b/tools/build/options/WITH_FMAKE index 72ae456dd9a5..9a98c8cfa1a9 100644 --- a/tools/build/options/WITH_FMAKE +++ b/tools/build/options/WITH_FMAKE @@ -1,4 +1,4 @@ .\" $FreeBSD$ -Causes the old FreeBSD +Causes the old FreeBSD .Xr make 1 program to be built and installed as fmake. diff --git a/tools/tools/ath/athaggrstats/Makefile b/tools/tools/ath/athaggrstats/Makefile index 43e2a66f148a..b6234b5fab79 100644 --- a/tools/tools/ath/athaggrstats/Makefile +++ b/tools/tools/ath/athaggrstats/Makefile @@ -12,8 +12,7 @@ CLEANFILES+= opt_ah.h CFLAGS+=-DATH_SUPPORT_ANI CFLAGS+=-DATH_SUPPORT_TDMA -USEPRIVATELIB= bsdstat -LDADD= ${LDBSDSTAT} +LIBADD+= bsdstat opt_ah.h: echo "#define AH_DEBUG 1" > opt_ah.h diff --git a/tools/tools/ath/athstats/Makefile b/tools/tools/ath/athstats/Makefile index 8d1bfa6269b4..a7ff43b4c9c2 100644 --- a/tools/tools/ath/athstats/Makefile +++ b/tools/tools/ath/athstats/Makefile @@ -23,9 +23,7 @@ CFLAGS+=-DATH_SUPPORT_TDMA CFLAGS.clang+= -fbracket-depth=512 -USEPRIVATELIB= bsdstat - -LDADD= ${LDBSDSTAT} +LIBADD= bsdstat opt_ah.h: echo "#define AH_DEBUG 1" > opt_ah.h diff --git a/tools/tools/mwl/mwlstats/Makefile b/tools/tools/mwl/mwlstats/Makefile index 4a3c5d3282fd..16decd1a4cd0 100644 --- a/tools/tools/mwl/mwlstats/Makefile +++ b/tools/tools/mwl/mwlstats/Makefile @@ -5,8 +5,7 @@ BINDIR= /usr/local/bin MAN= SRCS= main.c mwlstats.c -USEPRIVATELIB= -LDADD=-lbsdstat +LIBADD= bsdstat .include diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh index 685f4969a2f6..7789ef0999b8 100644 --- a/tools/tools/nanobsd/nanobsd.sh +++ b/tools/tools/nanobsd/nanobsd.sh @@ -213,13 +213,14 @@ clean_build ( ) ( chflags -R noschg ${MAKEOBJDIRPREFIX}/ nano_rm -r ${MAKEOBJDIRPREFIX}/ fi - mkdir -p ${MAKEOBJDIRPREFIX} - printenv > ${MAKEOBJDIRPREFIX}/_.env ) make_conf_build ( ) ( pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" + mkdir -p ${MAKEOBJDIRPREFIX} + printenv > ${MAKEOBJDIRPREFIX}/_.env + echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD} echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD} ) diff --git a/tools/tools/net80211/wlanstats/Makefile b/tools/tools/net80211/wlanstats/Makefile index 65d6468a9db5..dbd53a67e637 100644 --- a/tools/tools/net80211/wlanstats/Makefile +++ b/tools/tools/net80211/wlanstats/Makefile @@ -5,8 +5,7 @@ PROG= wlanstats BINDIR= /usr/local/bin MAN= -USEPRIVATELIB= bsdstat -LDADD= ${LDBSDSTAT} +LIBADD= bsdstat SRCS= wlanstats.c main.c diff --git a/tools/tools/npe/npestats/Makefile b/tools/tools/npe/npestats/Makefile index a4a404c2d8d2..20f381944776 100644 --- a/tools/tools/npe/npestats/Makefile +++ b/tools/tools/npe/npestats/Makefile @@ -4,7 +4,6 @@ PROG= npestats SRCS= main.c npestats.c BINDIR= /usr/local/bin MAN= -USEPRIVATELIB= -LDADD= -lbsdstat +LIBADD= bsdstat .include diff --git a/usr.bin/apply/Makefile b/usr.bin/apply/Makefile index 3ecf038f9282..223343455e6e 100644 --- a/usr.bin/apply/Makefile +++ b/usr.bin/apply/Makefile @@ -4,8 +4,8 @@ .include PROG= apply -DPADD= ${LIBSBUF} -LDADD= -lsbuf + +LIBADD= sbuf .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/usr.bin/ar/Makefile b/usr.bin/ar/Makefile index 157d4113309c..7a6601a7d043 100644 --- a/usr.bin/ar/Makefile +++ b/usr.bin/ar/Makefile @@ -5,8 +5,7 @@ PROG= ar SRCS= ar.c acplex.l acpyacc.y read.c util.c write.c y.tab.h -DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBZ} -LDADD= -larchive -lelf -lz +LIBADD= archive elf NO_WMISSING_VARIABLE_DECLARATIONS= diff --git a/usr.bin/atm/sscop/Makefile b/usr.bin/atm/sscop/Makefile index 36d3dcfc0280..cc688fd3dca6 100644 --- a/usr.bin/atm/sscop/Makefile +++ b/usr.bin/atm/sscop/Makefile @@ -8,7 +8,6 @@ PROG= sscop SRCS= common.c sscop_main.c CFLAGS+= -I${CONTRIB} -DUSE_LIBBEGEMOT -DPADD= ${LIBBEGEMOT} ${LIBNETGRAPH} ${LIBNGATM} -LDADD= -lbegemot -lnetgraph -lngatm +LIBADD= begemot ngatm .include diff --git a/usr.bin/awk/Makefile b/usr.bin/awk/Makefile index 65386365b180..a8bcb5c8b5e7 100644 --- a/usr.bin/awk/Makefile +++ b/usr.bin/awk/Makefile @@ -10,8 +10,7 @@ CFLAGS+= -DHAS_ISBLANK -I. -I${AWKSRC} -DFOPEN_MAX=64 WARNS?= 1 -DPADD= ${LIBM} -LDADD= -lm +LIBADD= m LINKS= ${BINDIR}/awk ${BINDIR}/nawk MLINKS= awk.1 nawk.1 diff --git a/usr.bin/bc/Makefile b/usr.bin/bc/Makefile index d2f26f135f6a..14d5677c355a 100644 --- a/usr.bin/bc/Makefile +++ b/usr.bin/bc/Makefile @@ -5,8 +5,7 @@ PROG= bc SRCS= bc.y scan.l tty.c CFLAGS+= -I. -I${.CURDIR} -DPADD+= ${LIBEDIT} ${LIBNCURSESW} -LDADD+= -ledit -lncursesw +LIBADD= edit NO_WMISSING_VARIABLE_DECLARATIONS= diff --git a/usr.bin/bluetooth/bthost/Makefile b/usr.bin/bluetooth/bthost/Makefile index 833d10721392..13b1d90d991c 100644 --- a/usr.bin/bluetooth/bthost/Makefile +++ b/usr.bin/bluetooth/bthost/Makefile @@ -3,7 +3,6 @@ PROG= bthost -DPADD= ${LIBBLUETOOTH} -LDADD= -lbluetooth +LIBADD= bluetooth .include diff --git a/usr.bin/bluetooth/btsockstat/Makefile b/usr.bin/bluetooth/btsockstat/Makefile index cdec9f7013c6..36ef850fc6d8 100644 --- a/usr.bin/bluetooth/btsockstat/Makefile +++ b/usr.bin/bluetooth/btsockstat/Makefile @@ -6,7 +6,6 @@ WARNS?= 2 BINGRP= kmem BINMODE= 2555 -DPADD= ${LIBBLUETOOTH} ${LIBKVM} -LDADD= -lbluetooth -lkvm +LIBADD= bluetooth kvm .include diff --git a/usr.bin/bluetooth/rfcomm_sppd/Makefile b/usr.bin/bluetooth/rfcomm_sppd/Makefile index 0da74981bc08..b17c5cfe4f37 100644 --- a/usr.bin/bluetooth/rfcomm_sppd/Makefile +++ b/usr.bin/bluetooth/rfcomm_sppd/Makefile @@ -5,7 +5,6 @@ PROG= rfcomm_sppd SRCS= rfcomm_sppd.c rfcomm_sdp.c WARNS?= 2 -DPADD= ${LIBBLUETOOTH} ${LIBSDP} -LDADD= -lbluetooth -lsdp -lutil +LIBADD= bluetooth sdp util .include diff --git a/usr.bin/bsdiff/bsdiff/Makefile b/usr.bin/bsdiff/bsdiff/Makefile index 0e8498f2be73..7569b4f10a35 100644 --- a/usr.bin/bsdiff/bsdiff/Makefile +++ b/usr.bin/bsdiff/bsdiff/Makefile @@ -2,7 +2,6 @@ PROG= bsdiff -DPADD= ${LIBBZ2} -LDADD= -lbz2 +LIBADD= bz2 .include diff --git a/usr.bin/bsdiff/bspatch/Makefile b/usr.bin/bsdiff/bspatch/Makefile index c0ed5219167f..c2d6d4e2f768 100644 --- a/usr.bin/bsdiff/bspatch/Makefile +++ b/usr.bin/bsdiff/bspatch/Makefile @@ -2,7 +2,6 @@ PROG= bspatch -DPADD= ${LIBBZ2} -LDADD= -lbz2 +LIBADD= bz2 .include diff --git a/usr.bin/bzip2/Makefile b/usr.bin/bzip2/Makefile index c2490a2bb5a1..5cb33b3d689d 100644 --- a/usr.bin/bzip2/Makefile +++ b/usr.bin/bzip2/Makefile @@ -8,8 +8,7 @@ CFLAGS+= -D_FILE_OFFSET_BITS=64 WARNS?= 3 -DPADD= ${LIBBZ2} -LDADD= -lbz2 +LIBADD= bz2 LINKS= ${BINDIR}/bzip2 ${BINDIR}/bunzip2 LINKS+= ${BINDIR}/bzip2 ${BINDIR}/bzcat diff --git a/usr.bin/calendar/Makefile b/usr.bin/calendar/Makefile index ef1d7f2dfc79..79101f0b9a44 100644 --- a/usr.bin/calendar/Makefile +++ b/usr.bin/calendar/Makefile @@ -6,8 +6,7 @@ PROG= calendar SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \ ostern.c paskha.c pom.c sunpos.c calcpp.c -DPADD= ${LIBM} -LDADD= -lm +LIBADD= m INTER= de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \ hr_HR.ISO8859-2 hu_HU.ISO8859-2 pt_BR.ISO8859-1 \ pt_BR.UTF-8 ru_RU.KOI8-R ru_RU.UTF-8 uk_UA.KOI8-U diff --git a/usr.bin/chkey/Makefile b/usr.bin/chkey/Makefile index a9e00e8a3d91..4f47b9cccccf 100644 --- a/usr.bin/chkey/Makefile +++ b/usr.bin/chkey/Makefile @@ -10,7 +10,6 @@ CFLAGS+= -I${.CURDIR}/../newkey .if ${MK_NIS} != "no" CFLAGS+= -DYP .endif -DPADD= ${LIBRPCSVC} ${LIBMP} ${LIBCRYPTO} -LDADD= -lrpcsvc -lmp -lcrypto +LIBADD+= rpcsvc mp .include diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile index cf3acc6bee15..9b3e878d8656 100644 --- a/usr.bin/chpass/Makefile +++ b/usr.bin/chpass/Makefile @@ -16,11 +16,9 @@ CFLAGS+= -DYP #CFLAGS+=-DRESTRICT_FULLNAME_CHANGE CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../lib/libc/gen -I. -DPADD= ${LIBCRYPT} ${LIBUTIL} -LDADD= -lcrypt -lutil +LIBADD= crypt util .if ${MK_NIS} != "no" -DPADD+= ${LIBYPCLNT} -LDADD+= -lypclnt +LIBADD+= ypclnt .endif LINKS= ${BINDIR}/chpass ${BINDIR}/chfn diff --git a/usr.bin/colldef/Makefile b/usr.bin/colldef/Makefile index c028e4af1e9e..fd59a6cc4939 100644 --- a/usr.bin/colldef/Makefile +++ b/usr.bin/colldef/Makefile @@ -5,8 +5,7 @@ SRCS= parse.y scan.l y.tab.h LFLAGS= -8 -i CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../lib/libc/locale CFLAGS+=-DCOLLATE_DEBUG -DYY_NO_UNPUT -DYY_NO_INPUT -LDADD= -ll -DPADD= ${LIBL} +LIBADD= l WARNS?= 2 diff --git a/usr.bin/compile_et/Makefile b/usr.bin/compile_et/Makefile index d7177b2f16fd..8af87ae10173 100644 --- a/usr.bin/compile_et/Makefile +++ b/usr.bin/compile_et/Makefile @@ -2,12 +2,9 @@ .PATH: ${.CURDIR}/../../contrib/com_err -LIBVERS= ${.OBJDIR}/../../kerberos5/lib/libvers/libvers.a - PROG= compile_et SRCS= compile_et.c parse.y lex.l -LDADD= -lroken ${LIBVERS} -DPADD= ${LIBROKEN} ${LIBVERS} +LIBADD= roken vers CFLAGS+=-I. -I${.CURDIR}/../../contrib/com_err WARNS?= 0 diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile index 16446c4b4def..72a0e2bd25a1 100644 --- a/usr.bin/cpio/Makefile +++ b/usr.bin/cpio/Makefile @@ -23,15 +23,7 @@ CFLAGS+= -I${LIBARCHIVEDIR}/cpio -I${LIBARCHIVEDIR}/libarchive_fe # statically linked, cannot use -lcrypto, and are size sensitive. CFLAGS+= -DSMALLER .endif -DPADD= ${LIBARCHIVE} ${LIBZ} ${LIBBZ2} ${LIBLZMA} ${LIBBSDXML} -LDADD= -larchive -lz -lbz2 -llzma -lbsdxml -.if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto -.else -DPADD+= ${LIBMD} -LDADD+= -lmd -.endif +LIBADD= archive .if ${MK_ICONV} != "no" CFLAGS+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DICONV_CONST=const diff --git a/usr.bin/cpio/test/Makefile b/usr.bin/cpio/test/Makefile index 13293b0b00ee..77c73d7274bb 100644 --- a/usr.bin/cpio/test/Makefile +++ b/usr.bin/cpio/test/Makefile @@ -67,10 +67,9 @@ CLEANFILES+= list.h bsdcpio_test MAN= PROG=bsdcpio_test -DPADD=${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBLZMA} CFLAGS+= -DPLATFORM_CONFIG_H=\"${.CURDIR}/../../../lib/libarchive/config_freebsd.h\" CFLAGS+= -I${.CURDIR}/../../../lib/libarchive -I${.OBJDIR} -LDADD= -larchive -lz -lbz2 -llzma +LIBADD= archive #CFLAGS+= -static -g -O2 -Wall CFLAGS+= -g -O2 -Wall CFLAGS+= -I${.OBJDIR} diff --git a/usr.bin/dc/Makefile b/usr.bin/dc/Makefile index 67af146f71cb..832b19771d65 100644 --- a/usr.bin/dc/Makefile +++ b/usr.bin/dc/Makefile @@ -3,7 +3,6 @@ PROG= dc SRCS= dc.c bcode.c inout.c mem.c stack.c -DPADD= ${LIBCRYPTO} -LDADD= -lcrypto +LIBADD= crypto .include diff --git a/usr.bin/dc/stack.c b/usr.bin/dc/stack.c index 950b4e5fdbf5..3364ae228c52 100644 --- a/usr.bin/dc/stack.c +++ b/usr.bin/dc/stack.c @@ -137,14 +137,12 @@ stack_swap(struct stack *stack) static void stack_grow(struct stack *stack) { - size_t i, new_size; + size_t new_size; if (++stack->sp == stack->size) { new_size = stack->size * 2 + 1; stack->stack = brealloc(stack->stack, new_size * sizeof(*stack->stack)); - for (i = stack->size; i < new_size; i++) - stack->stack[i].array = NULL; stack->size = new_size; } } @@ -156,6 +154,7 @@ stack_pushnumber(struct stack *stack, struct number *b) stack_grow(stack); stack->stack[stack->sp].type = BCODE_NUMBER; stack->stack[stack->sp].u.num = b; + stack->stack[stack->sp].array = NULL; } void @@ -165,6 +164,7 @@ stack_pushstring(struct stack *stack, char *string) stack_grow(stack); stack->stack[stack->sp].type = BCODE_STRING; stack->stack[stack->sp].u.string = string; + stack->stack[stack->sp].array = NULL; } void diff --git a/usr.bin/demandoc/Makefile b/usr.bin/demandoc/Makefile index d8682a462756..03a297bca208 100644 --- a/usr.bin/demandoc/Makefile +++ b/usr.bin/demandoc/Makefile @@ -4,9 +4,8 @@ PROG= demandoc -LDADD= ${LDMANDOC} -DPADD= ${LIBMANDOC} - WARNS?= 5 +LIBADD= mandoc + .include diff --git a/usr.bin/dpv/Makefile b/usr.bin/dpv/Makefile index 6f89c0fbb6b2..93a6cd10db52 100644 --- a/usr.bin/dpv/Makefile +++ b/usr.bin/dpv/Makefile @@ -4,8 +4,7 @@ PROG= dpv CFLAGS+= -I${.CURDIR} -DPADD= ${LIBDPV} ${LIBDIALOG} ${LIBFIGPAR} ${LIBNCURSESW} ${LIBUTIL} ${LIBM} -LDADD= -ldpv -ldialog -lfigpar -lncursesw -lutil -lm +LIBADD= dpv dialog WARNS?= 6 diff --git a/usr.bin/drill/Makefile b/usr.bin/drill/Makefile index 0db060482379..0de0ae52c2fc 100644 --- a/usr.bin/drill/Makefile +++ b/usr.bin/drill/Makefile @@ -12,8 +12,6 @@ CFLAGS+= -I${LDNSDIR} NO_WERROR= true MAN= drill.1 -DPADD+= ${LIBLDNS} ${LIBCRYPTO} -LDADD+= ${LDLDNS} -lcrypto -USEPRIVATELIB= ldns +LIBADD= ldns crypto .include diff --git a/usr.bin/du/Makefile b/usr.bin/du/Makefile index f614866da6de..9f96ec657a7e 100644 --- a/usr.bin/du/Makefile +++ b/usr.bin/du/Makefile @@ -2,7 +2,6 @@ # $FreeBSD$ PROG= du -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile index 8dcf2f569318..7423fa79d1b6 100644 --- a/usr.bin/ee/Makefile +++ b/usr.bin/ee/Makefile @@ -8,8 +8,7 @@ CFLAGS+= -DHAS_NCURSES -DHAS_UNISTD -DHAS_STDARG -DHAS_STDLIB \ PROG= ee LINKS= ${BINDIR}/ee ${BINDIR}/ree ${BINDIR}/ee ${BINDIR}/edit MLINKS= ee.1 ree.1 ee.1 edit.1 -DPADD= ${LIBNCURSESW} -LDADD= -lncursesw +LIBADD= ncursesw WARNS?= 2 diff --git a/usr.bin/enigma/Makefile b/usr.bin/enigma/Makefile index 32a670b07eca..55fcc468efd2 100644 --- a/usr.bin/enigma/Makefile +++ b/usr.bin/enigma/Makefile @@ -5,7 +5,6 @@ PROG= enigma LINKS= ${BINDIR}/enigma ${BINDIR}/crypt MLINKS= enigma.1 crypt.1 -DPADD= ${LIBCRYPT} -LDADD= -lcrypt +LIBADD= crypt .include diff --git a/usr.bin/fetch/Makefile b/usr.bin/fetch/Makefile index ed56f2f40c51..93c43a7c816b 100644 --- a/usr.bin/fetch/Makefile +++ b/usr.bin/fetch/Makefile @@ -1,15 +1,7 @@ # $FreeBSD$ -.include - PROG= fetch CSTD?= c99 -.if ${MK_OPENSSL} != "no" -DPADD= ${LIBFETCH} ${LIBSSL} ${LIBCRYPTO} -LDADD= -lfetch -lssl -lcrypto -.else -DPADD= ${LIBFETCH} ${LIBMD} -LDADD= -lfetch -lmd -.endif +LIBADD= fetch .include diff --git a/usr.bin/file/Makefile b/usr.bin/file/Makefile index 405436568594..70c211bd76db 100644 --- a/usr.bin/file/Makefile +++ b/usr.bin/file/Makefile @@ -31,8 +31,7 @@ MAGICPATH?= /usr/share/misc CFLAGS+= -DMAGIC='"${MAGICPATH}/magic"' -DHAVE_CONFIG_H CFLAGS+= -I${.CURDIR}/../../lib/libmagic -DPADD= ${LIBMAGIC} ${LIBZ} -LDADD= -lmagic -lz +LIBADD= magic FILEVER!= awk '$$1 == "\#define" && $$2 == "VERSION" { print $$3; exit }' \ ${.CURDIR}/../../lib/libmagic/config.h diff --git a/usr.bin/fstat/Makefile b/usr.bin/fstat/Makefile index 8ea8da3a473a..830b23c8cf21 100644 --- a/usr.bin/fstat/Makefile +++ b/usr.bin/fstat/Makefile @@ -4,8 +4,7 @@ PROG= fstat SRCS= fstat.c fuser.c main.c LINKS= ${BINDIR}/fstat ${BINDIR}/fuser -DPADD= ${LIBKVM} ${LIBUTIL} ${LIBPROCSTAT} -LDADD= -lkvm -lutil -lprocstat +LIBADD= procstat MAN1= fuser.1 fstat.1 diff --git a/usr.bin/ftp/Makefile b/usr.bin/ftp/Makefile index 3d236d8a9890..18068a64d454 100644 --- a/usr.bin/ftp/Makefile +++ b/usr.bin/ftp/Makefile @@ -20,8 +20,7 @@ CFLAGS+= -DINET6 .endif CFLAGS+= -I${.CURDIR} -I${TNFTP} -LDADD= -ledit -ltermcapw -DPADD= ${LIBEDIT} ${LIBTERMCAPW} +LIBADD= edit WARNS?= 2 diff --git a/usr.bin/gcore/Makefile b/usr.bin/gcore/Makefile index 7fff5403e50e..ad4b540f819b 100644 --- a/usr.bin/gcore/Makefile +++ b/usr.bin/gcore/Makefile @@ -3,8 +3,7 @@ PROG= gcore SRCS= elfcore.c gcore.c -DPADD= ${LIBSBUF} ${LIBUTIL} -LDADD= -lsbuf -lutil +LIBADD= sbuf util .if ${MACHINE_ARCH} == "amd64" SRCS+= elf32core.c diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile index 32941fd4ba4a..7dfde1409c40 100644 --- a/usr.bin/grep/Makefile +++ b/usr.bin/grep/Makefile @@ -40,12 +40,10 @@ MLINKS= grep.1 egrep.1 \ grep.1 lzfgrep.1 .endif -LDADD= -lz -DPADD= ${LIBZ} +LIBADD= z .if ${MK_LZMA_SUPPORT} != "no" -LDADD+= -llzma -DPADD+= ${LIBLZMA} +LIBADD+= lzma LINKS+= ${BINDIR}/${PROG} ${BINDIR}/xzgrep \ ${BINDIR}/${PROG} ${BINDIR}/xzegrep \ @@ -58,8 +56,7 @@ CFLAGS+= -DWITHOUT_LZMA .endif .if ${MK_BZIP2_SUPPORT} != "no" -LDADD+= -lbz2 -DPADD+= ${LIBBZ2} +LIBADD+= bz2 .if ${MK_BSD_GREP} == "yes" LINKS+= ${BINDIR}/grep ${BINDIR}/bzgrep \ @@ -75,8 +72,7 @@ CFLAGS+= -DWITHOUT_BZIP2 .if ${MK_GNU_GREP_COMPAT} != "no" CFLAGS+= -I${DESTDIR}/usr/include/gnu -LDADD+= -lgnuregex -DPADD+= ${LIBGNUREGEX} +LIBADD+= gnuregex .endif .if ${MK_NLS} != "no" diff --git a/usr.bin/gzip/Makefile b/usr.bin/gzip/Makefile index 24e250681cb8..1266277b16b1 100644 --- a/usr.bin/gzip/Makefile +++ b/usr.bin/gzip/Makefile @@ -6,12 +6,10 @@ PROG= gzip MAN= gzip.1 gzexe.1 zdiff.1 zforce.1 zmore.1 znew.1 -DPADD= ${LIBZ} ${LIBLZMA} -LDADD= -lz -llzma +LIBADD= z lzma .if ${MK_BZIP2_SUPPORT} != "no" -DPADD+= ${LIBBZ2} -LDADD+= -lbz2 +LIBADD+= bz2 .else CFLAGS+= -DNO_BZIP2_SUPPORT .endif diff --git a/usr.bin/host/Makefile b/usr.bin/host/Makefile index cc1111f115f9..5c2ce52b542c 100644 --- a/usr.bin/host/Makefile +++ b/usr.bin/host/Makefile @@ -15,8 +15,6 @@ host.1: ldns-host.1 (rm -rf ${.TARGET} ; false) CFLAGS+= -I${LDNSDIR} -DPADD+= ${LIBLDNS} ${LIBCRYPTO} -LDADD+= ${LDLDNS} -lcrypto -USEPRIVATELIB= ldns +LIBADD= ldns .include diff --git a/usr.bin/ipcrm/Makefile b/usr.bin/ipcrm/Makefile index f55311c11761..990b9f93f6bb 100644 --- a/usr.bin/ipcrm/Makefile +++ b/usr.bin/ipcrm/Makefile @@ -2,8 +2,7 @@ PROG= ipcrm SRCS= ipcrm.c ipc.c -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm CFLAGS+=-I${.CURDIR}/../ipcs .PATH: ${.CURDIR}/../ipcs diff --git a/usr.bin/ipcs/Makefile b/usr.bin/ipcs/Makefile index 0d422e189f62..310600408f77 100644 --- a/usr.bin/ipcs/Makefile +++ b/usr.bin/ipcs/Makefile @@ -2,8 +2,7 @@ PROG= ipcs SRCS= ipcs.c ipc.c -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm WARNS?= 1 diff --git a/usr.bin/iscsictl/Makefile b/usr.bin/iscsictl/Makefile index 9351ed71ae2a..afac7157ff3c 100644 --- a/usr.bin/iscsictl/Makefile +++ b/usr.bin/iscsictl/Makefile @@ -6,8 +6,7 @@ CFLAGS+= -I${.CURDIR} CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi MAN= iscsictl.8 -DPADD= ${LIBCAM} ${LIBUTIL} -LDADD= -lcam -lutil +LIBADD= cam util YFLAGS+= -v LFLAGS+= -i diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile index cba8e4102dab..94caaa98e70f 100644 --- a/usr.bin/kdump/Makefile +++ b/usr.bin/kdump/Makefile @@ -11,12 +11,11 @@ SFX= 32 PROG= kdump SRCS= kdump_subr.c kdump.c ioctl.c subr.c -DPSRCS= kdump_subr.h +DPSRCS= kdump_subr.h CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I. .if ${MK_CASPER} != "no" -DPADD+= ${LIBCAPSICUM} ${LIBNV} -LDADD+= -lcapsicum -lnv +LIBADD= capsicum CFLAGS+=-DHAVE_LIBCAPSICUM .endif diff --git a/usr.bin/keylogin/Makefile b/usr.bin/keylogin/Makefile index 4c03051a48f6..2dab2499319e 100644 --- a/usr.bin/keylogin/Makefile +++ b/usr.bin/keylogin/Makefile @@ -2,8 +2,7 @@ PROG= keylogin -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc WARNS?= 0 diff --git a/usr.bin/killall/Makefile b/usr.bin/killall/Makefile index de58c78dcb6a..890d7a126418 100644 --- a/usr.bin/killall/Makefile +++ b/usr.bin/killall/Makefile @@ -1,7 +1,6 @@ # $FreeBSD$ PROG= killall -DPADD= ${LIBJAIL} -LDADD= -ljail +LIBADD= jail .include diff --git a/usr.bin/ktrdump/Makefile b/usr.bin/ktrdump/Makefile index c30dc3d6d7e3..63cd2cf2cea9 100644 --- a/usr.bin/ktrdump/Makefile +++ b/usr.bin/ktrdump/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ PROG= ktrdump -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm MAN= ktrdump.8 WARNS?= 2 diff --git a/usr.bin/less/Makefile b/usr.bin/less/Makefile index 22147cd564fd..b6adf2c941f7 100644 --- a/usr.bin/less/Makefile +++ b/usr.bin/less/Makefile @@ -8,8 +8,7 @@ SRCS= main.c screen.c brac.c ch.c charset.c cmdbuf.c command.c cvt.c \ signal.c tags.c ttyin.c version.c SCRIPTS=lesspipe.sh zless.sh SCRIPTSNAME_lesspipe.sh=lesspipe.sh -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw LINKS= ${BINDIR}/less ${BINDIR}/more \ ${BINDIR}/zless ${BINDIR}/bzless \ ${BINDIR}/zless ${BINDIR}/xzless \ diff --git a/usr.bin/limits/Makefile b/usr.bin/limits/Makefile index 013317824db1..13ea5970cf2b 100644 --- a/usr.bin/limits/Makefile +++ b/usr.bin/limits/Makefile @@ -1,7 +1,6 @@ # $FreeBSD$ PROG= limits -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.bin/lock/Makefile b/usr.bin/lock/Makefile index dc09a87b1b9c..cc5d68907fbb 100644 --- a/usr.bin/lock/Makefile +++ b/usr.bin/lock/Makefile @@ -4,7 +4,7 @@ PROG= lock BINOWN= root BINMODE=4555 -DPADD= ${LIBCRYPT} -LDADD= -lcrypt + +LIBADD= crypt .include diff --git a/usr.bin/login/Makefile b/usr.bin/login/Makefile index 1ebc7602ad6d..0763c845b6ca 100644 --- a/usr.bin/login/Makefile +++ b/usr.bin/login/Makefile @@ -6,16 +6,14 @@ PROG= login SRCS= login.c login_fbtab.c CFLAGS+=-DLOGALL -DPADD= ${LIBUTIL} ${LIBPAM} -LDADD= -lutil ${MINUSLPAM} +LIBADD= util pam WARNS?= 5 .if ${MK_AUDIT} != "no" SRCS+= login_audit.c CFLAGS+= -DUSE_BSM_AUDIT -DPADD+= ${LIBBSM} -LDADD+= -lbsm +LIBADD+= bsm .endif .if ${MK_SETUID_LOGIN} != "no" diff --git a/usr.bin/lzmainfo/Makefile b/usr.bin/lzmainfo/Makefile index b92b46ccd8c9..158a2093be3a 100644 --- a/usr.bin/lzmainfo/Makefile +++ b/usr.bin/lzmainfo/Makefile @@ -16,7 +16,6 @@ CFLAGS+= -DHAVE_CONFIG_H \ -I${LZMALIBDIR} \ -I${XZDIR}/common -DPADD= ${LIBLZMA} -LDADD= -llzma +LIBADD= lzma .include diff --git a/usr.bin/m4/Makefile b/usr.bin/m4/Makefile index 9153e719eaed..d9550758f9b9 100644 --- a/usr.bin/m4/Makefile +++ b/usr.bin/m4/Makefile @@ -8,8 +8,7 @@ PROG= m4 CFLAGS+=-DEXTENDED -I${.CURDIR} -I${.CURDIR}/../../lib/libohash -DPADD= ${LIBY} ${LIBL} ${LIBM} ${LIBOHASH} -LDADD= -ly -ll -lm ${LDOHASH} +LIBADD= y l m ohash NO_WMISSING_VARIABLE_DECLARATIONS= diff --git a/usr.bin/makewhatis/Makefile b/usr.bin/makewhatis/Makefile index 4da90ef0f73f..ba0e1ee7decd 100644 --- a/usr.bin/makewhatis/Makefile +++ b/usr.bin/makewhatis/Makefile @@ -1,8 +1,7 @@ # $FreeBSD$ PROG= makewhatis -DPADD= ${LIBZ} -LDADD= -lz +LIBADD= z SCRIPTS= makewhatis.local.sh MAN= makewhatis.1 makewhatis.local.8 SCRIPTSDIR= /usr/libexec diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 481a3f9c5c73..ef3c05ff15f1 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,7 +1,6 @@ # $FreeBSD$ MDOCMLDIR= ${.CURDIR}/../../contrib/mdocml -LIBMANDOC= ${.OBJDIR}/../../lib/libmandoc/libmandoc.a .PATH: ${MDOCMLDIR} PROG= mandoc @@ -33,7 +32,6 @@ SRCS= ${HTML_SRCS} \ WARNS?= 3 CFLAGS+= -DHAVE_CONFIG_H -DPADD= ${LIBMANDOC} -LDADD= ${LIBMANDOC} +LIBADD= mandoc .include diff --git a/usr.bin/minigzip/Makefile b/usr.bin/minigzip/Makefile index b2cfc46f5773..da15aa9995ed 100644 --- a/usr.bin/minigzip/Makefile +++ b/usr.bin/minigzip/Makefile @@ -7,7 +7,6 @@ PROG= minigzip WARNS?= 5 CFLAGS+=-DUSE_MMAP -DPADD= ${LIBZ} -LDADD= -lz +LIBADD= z .include diff --git a/usr.bin/ministat/Makefile b/usr.bin/ministat/Makefile index e4c2f0718291..2a6379762883 100644 --- a/usr.bin/ministat/Makefile +++ b/usr.bin/ministat/Makefile @@ -1,13 +1,13 @@ # $FreeBSD$ PROG= ministat -DPADD= ${LIBM} -LDADD= -lm + +LIBADD= m .include test: ${PROG} - ./${PROG} < ${.CURDIR}/chameleon - ./${PROG} ${.CURDIR}/chameleon + ./${PROG} < ${.CURDIR}/chameleon + ./${PROG} ${.CURDIR}/chameleon ./${PROG} ${.CURDIR}/iguana ${.CURDIR}/chameleon ./${PROG} -c 80 ${.CURDIR}/iguana ${.CURDIR}/chameleon ./${PROG} -s -c 80 ${.CURDIR}/chameleon ${.CURDIR}/iguana diff --git a/usr.bin/mkimg/Makefile b/usr.bin/mkimg/Makefile index 28aac7ded9db..f028f3fcb988 100644 --- a/usr.bin/mkimg/Makefile +++ b/usr.bin/mkimg/Makefile @@ -31,8 +31,7 @@ SRCS+= \ BINDIR?=/usr/bin -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 6 diff --git a/usr.bin/mkulzma/Makefile b/usr.bin/mkulzma/Makefile index 8147ebfecf12..15596bfc22f2 100644 --- a/usr.bin/mkulzma/Makefile +++ b/usr.bin/mkulzma/Makefile @@ -2,7 +2,7 @@ PROG= mkulzma MAN= mkulzma.8 -DPADD= ${LIBLZMA} -LDADD= -llzma + +LIBADD= lzma .include diff --git a/usr.bin/mkuzip/Makefile b/usr.bin/mkuzip/Makefile index c5eac201776b..92ab43e897c7 100644 --- a/usr.bin/mkuzip/Makefile +++ b/usr.bin/mkuzip/Makefile @@ -3,8 +3,6 @@ PROG= mkuzip MAN= mkuzip.8 -DPADD= ${LIBZ} -LDADD= -lz - +LIBADD= z .include diff --git a/usr.bin/msgs/Makefile b/usr.bin/msgs/Makefile index 6c5a8d9b803a..3af95c31ea0d 100644 --- a/usr.bin/msgs/Makefile +++ b/usr.bin/msgs/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PROG= msgs -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw + +LIBADD= ncursesw .include diff --git a/usr.bin/nc/Makefile b/usr.bin/nc/Makefile index 17cea069429f..b24a086af97d 100644 --- a/usr.bin/nc/Makefile +++ b/usr.bin/nc/Makefile @@ -6,8 +6,7 @@ PROG= nc SRCS= netcat.c atomicio.c socks.c CFLAGS+=-DIPSEC -LDADD= -lipsec -DPADD= ${LIBIPSEC} +LIBADD= ipsec WARNS?= 2 diff --git a/usr.bin/ncal/Makefile b/usr.bin/ncal/Makefile index 1422ce1aae14..23b5da2ce492 100644 --- a/usr.bin/ncal/Makefile +++ b/usr.bin/ncal/Makefile @@ -4,8 +4,7 @@ PROG= ncal -DPADD= ${LIBCALENDAR} ${LIBTERMCAPW} -LDADD= -lcalendar -ltermcapw +LIBADD= calendar ncursesw LINKS= ${BINDIR}/ncal ${BINDIR}/cal MLINKS= ncal.1 cal.1 diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile index 2d50a495428b..89c8e0341f47 100644 --- a/usr.bin/netstat/Makefile +++ b/usr.bin/netstat/Makefile @@ -33,13 +33,11 @@ CFLAGS+=-DPF BINGRP= kmem BINMODE=2555 -DPADD= ${LIBKVM} ${LIBMEMSTAT} ${LIBUTIL} -LDADD= -lkvm -lmemstat -lutil +LIBADD= kvm memstat util .if ${MK_NETGRAPH_SUPPORT} != "no" SRCS+= netgraph.c -DPADD+= ${LIBNETGRAPH} -LDADD+= -lnetgraph +LIBADD+= netgraph CFLAGS+=-DNETGRAPH .endif diff --git a/usr.bin/newgrp/Makefile b/usr.bin/newgrp/Makefile index 8195348bf3f8..0a8e4a85e10c 100644 --- a/usr.bin/newgrp/Makefile +++ b/usr.bin/newgrp/Makefile @@ -1,8 +1,8 @@ # $FreeBSD$ PROG= newgrp -DPADD= ${LIBCRYPT} ${LIBUTIL} -LDADD= -lcrypt -lutil + +LIBADD= crypt util .if defined(ENABLE_SUID_NEWGRP) BINMODE= 4555 diff --git a/usr.bin/newkey/Makefile b/usr.bin/newkey/Makefile index bf4651352eed..be1ea3787fdb 100644 --- a/usr.bin/newkey/Makefile +++ b/usr.bin/newkey/Makefile @@ -8,7 +8,6 @@ SRCS= newkey.c generic.c update.c CFLAGS+= -DYP .endif MAN= newkey.8 -DPADD= ${LIBRPCSVC} ${LIBMP} ${LIBCRYPTO} -LDADD= -lrpcsvc -lmp -lcrypto +LIBADD= rpcsvc mp .include diff --git a/usr.bin/nfsstat/Makefile b/usr.bin/nfsstat/Makefile index d31db0aaf806..10b0b31e50e7 100644 --- a/usr.bin/nfsstat/Makefile +++ b/usr.bin/nfsstat/Makefile @@ -3,8 +3,8 @@ PROG= nfsstat CFLAGS+=-DNFS -DPADD= ${LIBKVM} -LDADD= -lkvm + +LIBADD= kvm WARNS?= 3 diff --git a/usr.bin/opieinfo/Makefile b/usr.bin/opieinfo/Makefile index b3ba166d7f69..f386be2bf628 100644 --- a/usr.bin/opieinfo/Makefile +++ b/usr.bin/opieinfo/Makefile @@ -10,8 +10,7 @@ CFLAGS+=-DINSECURE_OVERRIDE WARNS?= 0 -DPADD= ${LIBOPIE} ${LIBMD} -LDADD= -lopie -lmd +LIBADD= opie BINOWN= root BINMODE=4555 diff --git a/usr.bin/opiekey/Makefile b/usr.bin/opiekey/Makefile index 0ee85700f68c..95ae8b3e36f9 100644 --- a/usr.bin/opiekey/Makefile +++ b/usr.bin/opiekey/Makefile @@ -10,8 +10,7 @@ CFLAGS+=-DINSECURE_OVERRIDE WARNS?= 0 -DPADD= ${LIBOPIE} ${LIBMD} -LDADD= -lopie -lmd +LIBADD= opie LINKS= ${BINDIR}/opiekey ${BINDIR}/otp-md4 LINKS+= ${BINDIR}/opiekey ${BINDIR}/otp-md5 diff --git a/usr.bin/opiepasswd/Makefile b/usr.bin/opiepasswd/Makefile index b05e3b21e938..7b3f1f24bf95 100644 --- a/usr.bin/opiepasswd/Makefile +++ b/usr.bin/opiepasswd/Makefile @@ -10,8 +10,7 @@ CFLAGS+=-DINSECURE_OVERRIDE WARNS?= 0 -DPADD= ${LIBOPIE} ${LIBMD} -LDADD= -lopie -lmd +LIBADD= opie BINOWN= root BINMODE=4555 diff --git a/usr.bin/pamtest/Makefile b/usr.bin/pamtest/Makefile index 196830070de3..289beb64ea82 100644 --- a/usr.bin/pamtest/Makefile +++ b/usr.bin/pamtest/Makefile @@ -5,7 +5,7 @@ OPENPAM= ${.CURDIR}/../../contrib/openpam PROG= pamtest SRCS= pamtest.c -DPADD= ${LIBPAM} -LDADD= ${MINUSLPAM} + +LIBADD= pam .include diff --git a/usr.bin/passwd/Makefile b/usr.bin/passwd/Makefile index 3e6dc9393950..f1fff4668709 100644 --- a/usr.bin/passwd/Makefile +++ b/usr.bin/passwd/Makefile @@ -6,8 +6,7 @@ PROG = passwd BINOWN = root BINMODE = 4555 -DPADD = ${LIBPAM} -LDADD = ${MINUSLPAM} +LIBADD = pam .if ${MK_NIS} != "no" LINKS = ${BINDIR}/passwd ${BINDIR}/yppasswd MLINKS = passwd.1 yppasswd.1 diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile index 4def3110d15e..1744fe083214 100644 --- a/usr.bin/procstat/Makefile +++ b/usr.bin/procstat/Makefile @@ -16,7 +16,6 @@ SRCS= procstat.c \ procstat_threads.c \ procstat_vm.c -LDADD+= -lutil -lprocstat -lkvm -DPADD+= ${LIBUTIL} ${LIBPROCSTAT} ${LIBKVM} +LIBADD+= util procstat .include diff --git a/usr.bin/quota/Makefile b/usr.bin/quota/Makefile index 26585ae2b725..753972eb4389 100644 --- a/usr.bin/quota/Makefile +++ b/usr.bin/quota/Makefile @@ -5,7 +5,6 @@ PROG= quota BINOWN= root BINMODE=4555 -DPADD= ${LIBRPCSVC} ${LIBUTIL} -LDADD= -lrpcsvc -lutil +LIBADD= rpcsvc util .include diff --git a/usr.bin/rctl/Makefile b/usr.bin/rctl/Makefile index c5c32eba52eb..0191bdd811c3 100644 --- a/usr.bin/rctl/Makefile +++ b/usr.bin/rctl/Makefile @@ -3,7 +3,6 @@ PROG= rctl MAN= rctl.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.bin/rup/Makefile b/usr.bin/rup/Makefile index e87220168c22..4b5131e03c9c 100644 --- a/usr.bin/rup/Makefile +++ b/usr.bin/rup/Makefile @@ -4,7 +4,6 @@ PROG= rup WARNS?= 1 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc .include diff --git a/usr.bin/rusers/Makefile b/usr.bin/rusers/Makefile index 6cb39acd29e4..f64035094b7c 100644 --- a/usr.bin/rusers/Makefile +++ b/usr.bin/rusers/Makefile @@ -2,7 +2,6 @@ PROG = rusers -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc .include diff --git a/usr.bin/script/Makefile b/usr.bin/script/Makefile index 50ba12e696af..f75106fc24f9 100644 --- a/usr.bin/script/Makefile +++ b/usr.bin/script/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PROG= script -LDADD= -lutil -DPADD= ${LIBUTIL} + +LIBADD= util .include diff --git a/usr.bin/seq/Makefile b/usr.bin/seq/Makefile index 58b16aea7b05..bb3c2959a062 100644 --- a/usr.bin/seq/Makefile +++ b/usr.bin/seq/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PROG= seq -DPADD= ${LIBM} -LDADD= -lm + +LIBADD= m .include diff --git a/usr.bin/smbutil/Makefile b/usr.bin/smbutil/Makefile index 19ac5fd7343a..56367e889c53 100644 --- a/usr.bin/smbutil/Makefile +++ b/usr.bin/smbutil/Makefile @@ -3,8 +3,7 @@ PROG= smbutil SRCS= smbutil.c dumptree.c login.c lookup.c view.c print.c -DPADD= ${LIBSMB} ${LIBKICONV} -LDADD= -lsmb -lkiconv +LIBADD= smb kiconv CONTRIBDIR= ${.CURDIR}/../../contrib/smbfs CFLAGS+= -I${CONTRIBDIR}/include diff --git a/usr.bin/sort/Makefile b/usr.bin/sort/Makefile index 532e9307caab..d097beb370a5 100644 --- a/usr.bin/sort/Makefile +++ b/usr.bin/sort/Makefile @@ -13,12 +13,10 @@ CLEANFILES+= sort.1 .if ${MK_SORT_THREADS} != "no" CFLAGS+= -DSORT_THREADS -LDADD= -lpthread -lmd -DPADD= ${LIBPTHREAD} ${LIBMD} +LIBADD= pthread md MAN_SUB+= -e 's|%%THREADS%%||g' .else -LDADD= -lmd -DPADD= ${LIBMD} +LIBADD= md MAN_SUB+= -e 's|%%THREADS%%|\.\\"|g' .endif diff --git a/usr.bin/split/Makefile b/usr.bin/split/Makefile index 097932c19007..6891f8bbb4d7 100644 --- a/usr.bin/split/Makefile +++ b/usr.bin/split/Makefile @@ -2,7 +2,7 @@ # $FreeBSD$ PROG= split -LDADD= -lutil -DPADD= ${LIBUTIL} + +LIBADD= util .include diff --git a/usr.bin/su/Makefile b/usr.bin/su/Makefile index d5eb805e3f6e..178e670758c3 100644 --- a/usr.bin/su/Makefile +++ b/usr.bin/su/Makefile @@ -7,13 +7,11 @@ PROG= su WARNS?= 5 -DPADD= ${LIBUTIL} ${LIBPAM} -LDADD= -lutil ${MINUSLPAM} +LIBADD= util pam .if ${MK_AUDIT} != "no" CFLAGS+= -DUSE_BSM_AUDIT -DPADD+= ${LIBBSM} -LDADD+= -lbsm +LIBADD+= bsm .endif BINOWN= root diff --git a/usr.bin/svn/svn/Makefile b/usr.bin/svn/svn/Makefile index 24e2ec843b78..cdac81d7a4ae 100644 --- a/usr.bin/svn/svn/Makefile +++ b/usr.bin/svn/svn/Makefile @@ -39,18 +39,14 @@ LDADD= -L${LIBSVN_CLIENTDIR} -lsvn_client \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBSERFDIR} -lserf \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lmagic -lcrypto -lssl -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z magic crypto ssl pthread DPADD= ${LIBSVN_CLIENT} ${LIBSVN_WC} ${LIBSVN_RA} ${LIBSVN_RA_LOCAL} \ ${LIBSVN_RA_SVN} ${LIBSVN_RA_SERF} ${LIBSVN_REPOS} \ ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} ${LIBSVN_DELTA} \ ${LIBSVN_DIFF} ${LIBSVN_SUBR} ${LIBSERF} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBMAGIC} \ - ${LIBCRYPTO} ${LIBSSL} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} CLEANFILES+= svnlite.1 .if(defined(ORGANIZATION) && !empty(ORGANIZATION)) diff --git a/usr.bin/svn/svnadmin/Makefile b/usr.bin/svn/svnadmin/Makefile index afc7c0b05f80..00a9e2fb3f51 100644 --- a/usr.bin/svn/svnadmin/Makefile +++ b/usr.bin/svn/svnadmin/Makefile @@ -25,15 +25,11 @@ LDADD= -L${LIBSVN_REPOSDIR} -lsvn_repos \ -L${LIBSVN_DELTADIR} -lsvn_delta \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z pthread DPADD= ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} \ ${LIBSVN_DELTA} ${LIBSVN_SUBR} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBPTHREAD} - -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svndumpfilter/Makefile b/usr.bin/svn/svndumpfilter/Makefile index 995a6e6f2c24..44b4f075ba0c 100644 --- a/usr.bin/svn/svndumpfilter/Makefile +++ b/usr.bin/svn/svndumpfilter/Makefile @@ -25,14 +25,11 @@ LDADD= -L${LIBSVN_REPOSDIR} -lsvn_repos \ -L${LIBSVN_DELTADIR} -lsvn_delta \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z crypt pthread DPADD= ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} \ ${LIBSVN_DELTA} ${LIBSVN_SUBR} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svnlook/Makefile b/usr.bin/svn/svnlook/Makefile index 7e9968ee48c9..6e9f2faa39c9 100644 --- a/usr.bin/svn/svnlook/Makefile +++ b/usr.bin/svn/svnlook/Makefile @@ -26,14 +26,11 @@ LDADD= -L${LIBSVN_REPOSDIR} -lsvn_repos \ -L${LIBSVN_DIFFDIR} -lsvn_diff \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z pthread DPADD= ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} \ ${LIBSVN_DELTA} ${LIBSVN_DIFF} ${LIBSVN_SUBR} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svnmucc/Makefile b/usr.bin/svn/svnmucc/Makefile index 45c751115164..0b45ed6d3f0b 100644 --- a/usr.bin/svn/svnmucc/Makefile +++ b/usr.bin/svn/svnmucc/Makefile @@ -31,16 +31,12 @@ LDADD= -L${LIBSVN_CLIENTDIR} -lsvn_client \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBSERFDIR} -lserf \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lmagic -lcrypto -lssl -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z crypto ssl pthread DPADD= ${LIBSVN_CLIENT} ${LIBSVN_RA} ${LIBSVN_RA_LOCAL} ${LIBSVN_RA_SVN} \ ${LIBSVN_RA_SERF} ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} \ ${LIBSVN_FS_UTIL} ${LIBSVN_DELTA} ${LIBSVN_SUBR} ${LIBSERF} \ - ${LIBAPR_UTIL} ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} \ - ${LIBCRYPT} ${LIBMAGIC} ${LIBCRYPTO} ${LIBSSL} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR_UTIL} ${LIBAPR} .include diff --git a/usr.bin/svn/svnrdump/Makefile b/usr.bin/svn/svnrdump/Makefile index 8045e7bb0508..ca9022cdcc59 100644 --- a/usr.bin/svn/svnrdump/Makefile +++ b/usr.bin/svn/svnrdump/Makefile @@ -33,17 +33,13 @@ LDADD= -L${LIBSVN_CLIENTDIR} -lsvn_client \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBSERFDIR} -lserf \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lmagic -lcrypto -lssl -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z crypto ssl pthread DPADD= ${LIBSVN_CLIENT} ${LIBSVN_WC} ${LIBSVN_RA} ${LIBSVN_RA_LOCAL} \ ${LIBSVN_RA_SVN} ${LIBSVN_RA_SERF} ${LIBSVN_REPOS} \ ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} ${LIBSVN_DELTA} \ ${LIBSVN_DIFF} ${LIBSVN_SUBR} ${LIBSERF} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBMAGIC} \ - ${LIBCRYPTO} ${LIBSSL} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svnserve/Makefile b/usr.bin/svn/svnserve/Makefile index f01bbbdb8790..0622740a89d8 100644 --- a/usr.bin/svn/svnserve/Makefile +++ b/usr.bin/svn/svnserve/Makefile @@ -30,16 +30,12 @@ LDADD= -L${LIBSVN_RADIR} -lsvn_ra \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBSERFDIR} -lserf \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lmagic -lcrypto -lssl -lpthread + -L${LIBAPRDIR} -lapr +LIBADD= bsdxml sqlite3 z pthread DPADD= ${LIBSVN_RA} ${LIBSVN_RA_LOCAL} ${LIBSVN_RA_SVN} ${LIBSVN_RA_SERF} \ ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} \ ${LIBSVN_DELTA} ${LIBSVN_SUBR} ${LIBSERF} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBMAGIC} \ - ${LIBCRYPTO} ${LIBSSL} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svnsync/Makefile b/usr.bin/svn/svnsync/Makefile index 7bba53403f2f..4417760dd146 100644 --- a/usr.bin/svn/svnsync/Makefile +++ b/usr.bin/svn/svnsync/Makefile @@ -30,16 +30,12 @@ LDADD= -L${LIBSVN_RADIR} -lsvn_ra \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBSERFDIR} -lserf \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lmagic -lcrypto -lssl -lpthread + -L${LIBAPRDIR} -lapr +LIBADD= bsdxml sqlite3 z crypto ssl pthread DPADD= ${LIBSVN_RA} ${LIBSVN_RA_LOCAL} ${LIBSVN_RA_SVN} ${LIBSVN_RA_SERF} \ ${LIBSVN_REPOS} ${LIBSVN_FS} ${LIBSVN_FS_FS} ${LIBSVN_FS_UTIL} \ ${LIBSVN_DELTA} ${LIBSVN_SUBR} ${LIBSERF} ${LIBAPR_UTIL} \ - ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} ${LIBZ} ${LIBCRYPT} ${LIBMAGIC} \ - ${LIBCRYPTO} ${LIBSSL} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBAPR} .include diff --git a/usr.bin/svn/svnversion/Makefile b/usr.bin/svn/svnversion/Makefile index ac45431f9c69..594ba34f01ba 100644 --- a/usr.bin/svn/svnversion/Makefile +++ b/usr.bin/svn/svnversion/Makefile @@ -23,14 +23,10 @@ LDADD= -L${LIBSVN_WCDIR} -lsvn_wc \ -L${LIBSVN_DIFFDIR} -lsvn_diff \ -L${LIBSVN_SUBRDIR} -lsvn_subr \ -L${LIBAPR_UTILDIR} -lapr-util \ - -lbsdxml \ - -L${LIBAPRDIR} -lapr \ - ${LDSQLITE3} \ - -lz -lcrypt -lpthread + -L${LIBAPRDIR} -lapr +LIBADD+= bsdxml sqlite3 z pthread DPADD= ${LIBSVN_WC} ${LIBSVN_DELTA} ${LIBSVN_DIFF} ${LIBSVN_SUBR} \ - ${LIBSERF} ${LIBAPR_UTIL} ${LIBBSDXML} ${LIBAPR} ${LIBSQLITE3} \ - ${LIBZ} ${LIBCRYPT} ${LIBPTHREAD} -USEPRIVATELIB= sqlite3 + ${LIBSERF} ${LIBAPR_UTIL}${LIBAPR} .include diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile index 1bb2da05a052..672aadcea5ae 100644 --- a/usr.bin/systat/Makefile +++ b/usr.bin/systat/Makefile @@ -16,7 +16,6 @@ CFLAGS+= -DINET6 WARNS?= 0 -DPADD= ${LIBNCURSESW} ${LIBM} ${LIBDEVSTAT} ${LIBKVM} -LDADD= -lncursesw -lm -ldevstat -lkvm +LIBADD= ncursesw m devstat kvm .include diff --git a/usr.bin/tabs/Makefile b/usr.bin/tabs/Makefile index 2c5f729905a1..f8c085bfbe80 100644 --- a/usr.bin/tabs/Makefile +++ b/usr.bin/tabs/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ PROG= tabs -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw + +LIBADD= ncursesw .include diff --git a/usr.bin/talk/Makefile b/usr.bin/talk/Makefile index eb14d22ab8c2..f595be8839c4 100644 --- a/usr.bin/talk/Makefile +++ b/usr.bin/talk/Makefile @@ -4,7 +4,7 @@ PROG= talk SRCS= ctl.c ctl_transact.c display.c get_addrs.c get_iface.c get_names.c \ init_disp.c invite.c io.c look_up.c msgs.c talk.c -DPADD= ${LIBNCURSESW} -LDADD= -lncursesw + +LIBADD= ncursesw .include diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile index a289ea49a7ce..f7e7775a1764 100644 --- a/usr.bin/tar/Makefile +++ b/usr.bin/tar/Makefile @@ -19,15 +19,7 @@ SRCS= bsdtar.c \ SRCS+= err.c \ line_reader.c -DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBLZMA} ${LIBBSDXML} -LDADD= -larchive -lbz2 -lz -llzma -lbsdxml -.if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto -.else -DPADD+= ${LIBMD} -LDADD+= -lmd -.endif +LIBADD= archive .if ${MK_ICONV} != "no" CFLAGS+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DICONV_CONST=const diff --git a/usr.bin/telnet/Makefile b/usr.bin/telnet/Makefile index b88f8e1a532c..a24a9669fb55 100644 --- a/usr.bin/telnet/Makefile +++ b/usr.bin/telnet/Makefile @@ -19,15 +19,11 @@ CFLAGS+= -DINET6 WARNS?= 2 -LIBTELNET= ${.OBJDIR}/../../lib/libtelnet/libtelnet.a - -DPADD= ${LIBTERMCAPW} ${LIBTELNET} -LDADD= -ltermcapw ${LIBTELNET} +LIBADD= telnet ncursesw .if !defined(RELEASE_CRUNCH) CFLAGS+= -DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec +LIBADD+= ipsec .else .PATH: ${TELNETDIR}/libtelnet SRCS+= genget.c getent.c misc.c @@ -35,16 +31,14 @@ CFLAGS+= -DHAS_CGETENT .endif .if ${MK_OPENSSL} != "no" -SRCS+= authenc.c +SRCS+= authenc.c CFLAGS+= -DENCRYPTION -DAUTHENTICATION -DIPSEC -DPADD+= ${LIBMP} ${LIBCRYPTO} ${LIBCRYPT} ${LIBIPSEC} ${LIBPAM} -LDADD+= -lmp -lcrypto -lcrypt -lipsec ${MINUSLPAM} +LIBADD+= mp crypto ipsec pam .endif .if ${MK_KERBEROS_SUPPORT} != "no" CFLAGS+= -DKRB5 -DFORWARD -Dnet_write=telnet_net_write -DPADD+= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBCOM_ERR} ${LIBROKEN} -LDADD+= -lkrb5 -lhx509 -lasn1 -lcom_err -lroken +LIBADD+= krb5 roken .endif .include diff --git a/usr.bin/tftp/Makefile b/usr.bin/tftp/Makefile index 88f8c373ac38..0f96d232c0e1 100644 --- a/usr.bin/tftp/Makefile +++ b/usr.bin/tftp/Makefile @@ -7,7 +7,7 @@ PROG= tftp SRCS= main.c tftp-file.c tftp-io.c tftp-options.c tftp-transfer.c SRCS+= tftp-utils.c tftp.c CFLAGS+=-I${.CURDIR}/../../libexec/tftpd -DPADD= ${LIBEDIT} ${LIBTERMCAPW} -LDADD= -ledit -ltermcapw + +LIBADD= edit .include diff --git a/usr.bin/top/Makefile b/usr.bin/top/Makefile index de08724f7bce..67ab20d8d79a 100644 --- a/usr.bin/top/Makefile +++ b/usr.bin/top/Makefile @@ -21,8 +21,7 @@ WARNS?= 0 CFLAGS+= -D"Table_size=${TOP_TABLE_SIZE}" .endif -DPADD= ${LIBTERMCAP} ${LIBM} ${LIBKVM} ${LIBJAIL} -LDADD= -ltermcap -lm -lkvm -ljail +LIBADD= ncursesw m kvm jail CLEANFILES= sigdesc.h SIGCONV_AWK= ${.CURDIR}/../../contrib/top/sigconv.awk diff --git a/usr.bin/tput/Makefile b/usr.bin/tput/Makefile index c42ef7925190..d3171dab7ef0 100644 --- a/usr.bin/tput/Makefile +++ b/usr.bin/tput/Makefile @@ -2,8 +2,7 @@ # $FreeBSD$ PROG= tput -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw SCRIPTS=clear.sh MLINKS= tput.1 clear.1 diff --git a/usr.bin/truncate/Makefile b/usr.bin/truncate/Makefile index b51c9b0d3fc7..a6de5c6c9ba0 100644 --- a/usr.bin/truncate/Makefile +++ b/usr.bin/truncate/Makefile @@ -2,9 +2,8 @@ .include -PROG= truncate -DPADD= ${LIBUTIL} -LDADD= -lutil +PROG= truncate +LIBADD= util .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/usr.bin/tset/Makefile b/usr.bin/tset/Makefile index c486bf8eaca8..acf833495428 100644 --- a/usr.bin/tset/Makefile +++ b/usr.bin/tset/Makefile @@ -4,8 +4,7 @@ PROG= tset SRCS= map.c misc.c set.c term.c tset.c wrterm.c -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw LINKS= ${BINDIR}/tset ${BINDIR}/reset MLINKS= tset.1 reset.1 diff --git a/usr.bin/ul/Makefile b/usr.bin/ul/Makefile index 685e4a4a292c..817f07ba14cb 100644 --- a/usr.bin/ul/Makefile +++ b/usr.bin/ul/Makefile @@ -3,7 +3,6 @@ PROG= ul -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw .include diff --git a/usr.bin/units/Makefile b/usr.bin/units/Makefile index 3757c857509e..901886643fbd 100644 --- a/usr.bin/units/Makefile +++ b/usr.bin/units/Makefile @@ -6,8 +6,7 @@ PROG= units FILES= units.lib FILESDIR= ${SHAREDIR}/misc -LDADD+=-ledit -ltermcapw -DPADD+=${LIBEDIT} ${LIBTERMCAPW} +LIBADD= edit .if ${MK_TESTS} != "no" SUBDIR+= tests diff --git a/usr.bin/unzip/Makefile b/usr.bin/unzip/Makefile index ef8a69072686..9ed1a950c77d 100644 --- a/usr.bin/unzip/Makefile +++ b/usr.bin/unzip/Makefile @@ -2,7 +2,6 @@ PROG = unzip CSTD = c99 -DPADD = ${LIBARCHIVE} ${LIBZ} -LDADD = -larchive -lz +LIBADD= archive .include diff --git a/usr.bin/usbhidaction/Makefile b/usr.bin/usbhidaction/Makefile index 6c2f7a6b8496..7aadd6cd6edd 100644 --- a/usr.bin/usbhidaction/Makefile +++ b/usr.bin/usbhidaction/Makefile @@ -3,7 +3,6 @@ PROG= usbhidaction -LDADD= -lusbhid -DPADD= ${LIBUSBHID} +LIBADD= usbhid .include diff --git a/usr.bin/usbhidctl/Makefile b/usr.bin/usbhidctl/Makefile index 3738b506cea2..f0b5758bb936 100644 --- a/usr.bin/usbhidctl/Makefile +++ b/usr.bin/usbhidctl/Makefile @@ -3,7 +3,7 @@ PROG= usbhidctl SRCS= usbhid.c -DPADD= ${LIBUSBHID} -LDADD= -lusbhid + +LIBADD= usbhid .include diff --git a/usr.bin/vacation/Makefile b/usr.bin/vacation/Makefile index 056f5764fa01..f32e0c4c3b03 100644 --- a/usr.bin/vacation/Makefile +++ b/usr.bin/vacation/Makefile @@ -11,17 +11,7 @@ CFLAGS+=-D_FFR_LISTDB -D_FFR_DEBUG WARNS?= 2 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMDBDIR= ${.OBJDIR}/../../lib/libsmdb -LIBSMDB= ${LIBSMDBDIR}/libsmdb.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} -LDADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} +LIBADD= smdb smutil sm SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/usr.bin/vi/Makefile b/usr.bin/vi/Makefile index 820bc3f55738..1bbdb5c585b3 100644 --- a/usr.bin/vi/Makefile +++ b/usr.bin/vi/Makefile @@ -33,12 +33,8 @@ MLINKS+=vi.1 nex.1 vi.1 nview.1 vi.1 nvi.1 CFLAGS+=-I${.CURDIR} -I${SRCDIR} -I${SRCDIR}/regex -DPADD= ${LIBUTIL} -LDADD= -lutil - +LIBADD= util ncursesw CFLAGS+= -DUSE_WIDECHAR -DPADD+= ${LIBNCURSESW} -LDADD+= -lncursesw .if ${MK_ICONV} == "yes" && !defined(RESCUE) && !defined(RELEASE_CRUNCH) CFLAGS+= -DUSE_ICONV diff --git a/usr.bin/vmstat/Makefile b/usr.bin/vmstat/Makefile index d413d25ab61a..8945b3d46126 100644 --- a/usr.bin/vmstat/Makefile +++ b/usr.bin/vmstat/Makefile @@ -3,8 +3,7 @@ PROG= vmstat MAN= vmstat.8 -DPADD= ${LIBDEVSTAT} ${LIBKVM} ${LIBMEMSTAT} ${LIBUTIL} -LDADD= -ldevstat -lkvm -lmemstat -lutil +LIBADD= devstat kvm memstat util WARNS?= 1 diff --git a/usr.bin/w/Makefile b/usr.bin/w/Makefile index 6a5bbe514a41..cb7a0639bea0 100644 --- a/usr.bin/w/Makefile +++ b/usr.bin/w/Makefile @@ -4,8 +4,7 @@ PROG= w SRCS= fmt.c pr_time.c proc_compare.c w.c MAN= w.1 uptime.1 -DPADD= ${LIBKVM} ${LIBUTIL} ${LIBXO} -LDADD= -lkvm -lutil -lxo +LIBADD= kvm util xo #BINGRP= kmem #BINMODE=2555 LINKS= ${BINDIR}/w ${BINDIR}/uptime diff --git a/usr.bin/wc/Makefile b/usr.bin/wc/Makefile index 6c671353be69..540e33d15c92 100644 --- a/usr.bin/wc/Makefile +++ b/usr.bin/wc/Makefile @@ -2,7 +2,6 @@ # $FreeBSD$ PROG= wc -DPADD= ${LIBXO} -LDADD= -lxo +LIBADD= xo .include diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile index 773dd4ef8778..1d3927321f25 100644 --- a/usr.bin/xinstall/Makefile +++ b/usr.bin/xinstall/Makefile @@ -12,7 +12,6 @@ CFLAGS+= -I${.CURDIR}/../../contrib/mtree CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd CFLAGS+= -I${.CURDIR}/../../lib/libmd -DPADD+= ${LIBMD} -LDADD+= -lmd +LIBADD= md .include diff --git a/usr.bin/xlint/lint1/Makefile b/usr.bin/xlint/lint1/Makefile index b7f78c5afb26..2d6539eb4b2a 100644 --- a/usr.bin/xlint/lint1/Makefile +++ b/usr.bin/xlint/lint1/Makefile @@ -7,8 +7,7 @@ SRCS= cgram.y scan.l mem1.c mem.c err.c main1.c decl.c tree.c func.c \ MAN= lint.7 CLEANFILES= lint.7 -LDADD= -ll -lm -DPADD= ${LIBL} ${LIBM} +LIBADD= l m CFLAGS+= -I. -I${.CURDIR} LINTFLAGS=-aehpz diff --git a/usr.bin/xo/Makefile b/usr.bin/xo/Makefile index c7b51d8e1d86..b199207e9055 100644 --- a/usr.bin/xo/Makefile +++ b/usr.bin/xo/Makefile @@ -10,7 +10,6 @@ MAN= xo.1 # XXX For xoversion.h CFLAGS+=-I${LIBXO}/libxo -DPADD= ${LIBXO} -LDADD= -lxo +LIBADD= xo .include diff --git a/usr.bin/xz/Makefile b/usr.bin/xz/Makefile index 13703fd5bc9a..e2eaca58fcf3 100644 --- a/usr.bin/xz/Makefile +++ b/usr.bin/xz/Makefile @@ -42,7 +42,6 @@ CFLAGS+= -DHAVE_CONFIG_H \ -I${LZMALIBDIR} \ -I${XZDIR}/common -DPADD= ${LIBLZMA} -LDADD= -llzma +LIBADD= lzma .include diff --git a/usr.bin/xzdec/Makefile b/usr.bin/xzdec/Makefile index daef296f250b..f78a16c93905 100644 --- a/usr.bin/xzdec/Makefile +++ b/usr.bin/xzdec/Makefile @@ -22,7 +22,6 @@ CFLAGS+= -DHAVE_CONFIG_H \ -I${LZMALIBDIR} \ -I${XZDIR}/common -DPADD= ${LIBLZMA} -LDADD= -llzma +LIBADD= lzma .include diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile index 15d114d7892e..9df03bd7b154 100644 --- a/usr.sbin/acpi/acpidb/Makefile +++ b/usr.sbin/acpi/acpidb/Makefile @@ -74,7 +74,6 @@ MAN= acpidb.8 WARNS?= 3 CFLAGS+= -DACPI_EXEC_APP -fno-strict-aliasing -DPADD= ${LIBPTHREAD} -LDADD= -lpthread +LIBADD= pthread .include diff --git a/usr.sbin/amd/Makefile.inc b/usr.sbin/amd/Makefile.inc index e4425f52a2c5..8c397cfcc958 100644 --- a/usr.sbin/amd/Makefile.inc +++ b/usr.sbin/amd/Makefile.inc @@ -29,13 +29,6 @@ CFLAGS+= -DYES_HESIOD CFLAGS+= -DHOST_CPU=\"${MACHINE_CPUARCH}\" -DHOST_ARCH=\"${MACHINE_ARCH}\" -.if exists(${.OBJDIR}/../libamu) -LIBAMUDIR= ${.OBJDIR}/../libamu -.else -LIBAMUDIR= ${.CURDIR}/../libamu -.endif -LIBAMU= ${LIBAMUDIR}/libamu.a - RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen MOUNT_X= ${DESTDIR}/usr/include/rpcsvc/mount.x NFS_PROT_X= ${DESTDIR}/usr/include/rpcsvc/nfs_prot.x diff --git a/usr.sbin/amd/amd/Makefile b/usr.sbin/amd/amd/Makefile index 1fc41bfe20d0..602c9411eb63 100644 --- a/usr.sbin/amd/amd/Makefile +++ b/usr.sbin/amd/amd/Makefile @@ -27,8 +27,7 @@ SRCS+= srvr_amfs_auto.c srvr_nfs.c CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amd \ -I${DESTDIR}/usr/include/rpcsvc -DPADD= ${LIBAMU} ${LIBWRAP} -LDADD= ${LIBAMU} -lwrap +LIBADD= amu wrap CLEANFILES+= conf_parse.c conf_parse.h conf_tok.c diff --git a/usr.sbin/amd/amq/Makefile b/usr.sbin/amd/amq/Makefile index 74fc7492f524..968ae4c7b044 100644 --- a/usr.sbin/amd/amq/Makefile +++ b/usr.sbin/amd/amq/Makefile @@ -14,7 +14,6 @@ SRCS= amq.c amq_clnt.c amq_xdr.c CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amq -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu .include diff --git a/usr.sbin/amd/fixmount/Makefile b/usr.sbin/amd/fixmount/Makefile index 7f96a456dfe4..8137ffb3fdb7 100644 --- a/usr.sbin/amd/fixmount/Makefile +++ b/usr.sbin/amd/fixmount/Makefile @@ -10,12 +10,11 @@ PROG= fixmount MAN= fixmount.8 -SRCS= fixmount.c +SRCS= fixmount.c # These would be links created by the GNU-style configure SRCS+= checkmount_bsd44.c -DPADD= ${LIBAMU} ${LIBRPCSVC} -LDADD= ${LIBAMU} -lrpcsvc +LIBADD+= amu rpcsvc .include diff --git a/usr.sbin/amd/fsinfo/Makefile b/usr.sbin/amd/fsinfo/Makefile index 1695a469f980..a059da690e43 100644 --- a/usr.sbin/amd/fsinfo/Makefile +++ b/usr.sbin/amd/fsinfo/Makefile @@ -15,8 +15,7 @@ SRCS+= wr_bparam.c wr_dumpset.c wr_exportfs.c wr_fstab.c CFLAGS+= -I${.CURDIR}/../../../contrib/amd/fsinfo -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu CLEANFILES+= fsi_gram.c fsi_gram.h fsi_lex.c diff --git a/usr.sbin/amd/hlfsd/Makefile b/usr.sbin/amd/hlfsd/Makefile index 5b863dd5adcd..96d05c4f17ff 100644 --- a/usr.sbin/amd/hlfsd/Makefile +++ b/usr.sbin/amd/hlfsd/Makefile @@ -13,7 +13,6 @@ SRCS= hlfsd.c homedir.c nfs_prot_svc.c stubs.c CFLAGS+= -I${.CURDIR}/../../../contrib/amd/hlfsd -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu .include diff --git a/usr.sbin/amd/mk-amd-map/Makefile b/usr.sbin/amd/mk-amd-map/Makefile index 57fd6a5f0bdc..417ea2a85cf1 100644 --- a/usr.sbin/amd/mk-amd-map/Makefile +++ b/usr.sbin/amd/mk-amd-map/Makefile @@ -10,7 +10,6 @@ PROG= mk-amd-map MAN= mk-amd-map.8 -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu .include diff --git a/usr.sbin/amd/pawd/Makefile b/usr.sbin/amd/pawd/Makefile index c6bb1cc37a0b..2870ab4cd833 100644 --- a/usr.sbin/amd/pawd/Makefile +++ b/usr.sbin/amd/pawd/Makefile @@ -14,7 +14,6 @@ SRCS= pawd.c amq_clnt.c amq_xdr.c CFLAGS+= -I${.CURDIR}/../../../contrib/amd/amq -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu .include diff --git a/usr.sbin/amd/wire-test/Makefile b/usr.sbin/amd/wire-test/Makefile index a07e6902fe76..edde2eb67d5b 100644 --- a/usr.sbin/amd/wire-test/Makefile +++ b/usr.sbin/amd/wire-test/Makefile @@ -10,7 +10,6 @@ PROG= wire-test MAN= wire-test.8 -DPADD= ${LIBAMU} -LDADD= ${LIBAMU} +LIBADD= amu .include diff --git a/usr.sbin/ancontrol/Makefile b/usr.sbin/ancontrol/Makefile index b0f66cd15a86..f06b943e732d 100644 --- a/usr.sbin/ancontrol/Makefile +++ b/usr.sbin/ancontrol/Makefile @@ -6,7 +6,6 @@ MAN= ancontrol.8 WARNS?= 3 CFLAGS+= -DANCACHE -I${.CURDIR}/../../sys -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/usr.sbin/apmd/Makefile b/usr.sbin/apmd/Makefile index 9a0dc0dd4652..b2afdfaf78d1 100644 --- a/usr.sbin/apmd/Makefile +++ b/usr.sbin/apmd/Makefile @@ -7,8 +7,7 @@ SRCS= apmd.c apmdlex.l apmdparse.y y.tab.h WARNS?= 3 -DPADD= ${LIBL} -LDADD= -ll +LIBADD= l CFLAGS+= -I${.CURDIR} diff --git a/usr.sbin/asf/Makefile b/usr.sbin/asf/Makefile index 0db69e82cc6d..49f93059923c 100644 --- a/usr.sbin/asf/Makefile +++ b/usr.sbin/asf/Makefile @@ -4,7 +4,6 @@ PROG= asf SRCS= asf.c asf_kld.c asf_kvm.c asf_prog.c MAN= asf.8 -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm .include diff --git a/usr.sbin/audit/Makefile b/usr.sbin/audit/Makefile index a3f7fbf241fd..14fc893584aa 100644 --- a/usr.sbin/audit/Makefile +++ b/usr.sbin/audit/Makefile @@ -10,8 +10,7 @@ CFLAGS+= -I${OPENBSMDIR} PROG= audit MAN= audit.8 -DPADD= ${LIBBSM} -LDADD= -lbsm +LIBADD= bsm WARNS?= 5 diff --git a/usr.sbin/auditd/Makefile b/usr.sbin/auditd/Makefile index 47ffd0b915d0..3fb6a409fa8c 100644 --- a/usr.sbin/auditd/Makefile +++ b/usr.sbin/auditd/Makefile @@ -11,8 +11,7 @@ PROG= auditd SRCS= auditd.c audit_warn.c auditd_fbsd.c MAN= auditd.8 -DPADD= ${LIBAUDITD} ${LIBBSM} -LDADD= -lauditd -lbsm +LIBADD= auditd bsm WARNS?= 3 diff --git a/usr.sbin/auditdistd/Makefile b/usr.sbin/auditdistd/Makefile index b323dcd3e9cb..8d32884bda49 100644 --- a/usr.sbin/auditdistd/Makefile +++ b/usr.sbin/auditdistd/Makefile @@ -21,10 +21,7 @@ SRCS+= sandbox.c sender.c subr.c SRCS+= token.l trail.c MAN= auditdistd.8 auditdistd.conf.5 -DPADD= ${LIBL} ${LIBPTHREAD} ${LIBUTIL} -LDADD= -ll -lpthread -lutil -DPADD+= ${LIBCRYPTO} ${LIBSSL} -LDADD+= -lcrypto -lssl +LIBADD+= l pthread util crypto ssl YFLAGS+=-v diff --git a/usr.sbin/auditreduce/Makefile b/usr.sbin/auditreduce/Makefile index 7dc955337da1..a462e1b9c4b8 100644 --- a/usr.sbin/auditreduce/Makefile +++ b/usr.sbin/auditreduce/Makefile @@ -10,8 +10,7 @@ CFLAGS+= -I${OPENBSMDIR} PROG= auditreduce MAN= auditreduce.1 -DPADD= ${LIBBSM} -LDADD= -lbsm +LIBADD= bsm WARNS?= 3 diff --git a/usr.sbin/authpf/Makefile b/usr.sbin/authpf/Makefile index 744df6118d3a..07b2cdc2067f 100644 --- a/usr.sbin/authpf/Makefile +++ b/usr.sbin/authpf/Makefile @@ -13,8 +13,7 @@ SRCS= authpf.c # XXX ALTQ: CFLAGS+= -DENABLE_ALTQ -LDADD+= -lm -lmd -lutil -DPADD+= ${LIBM} ${LIBMD} ${LIBUTIL} +LIBADD= m md util WARNS?= 3 diff --git a/usr.sbin/autofs/Makefile b/usr.sbin/autofs/Makefile index fab6865a8906..00c79dddba6e 100644 --- a/usr.sbin/autofs/Makefile +++ b/usr.sbin/autofs/Makefile @@ -16,8 +16,7 @@ CFLAGS+=-I${.CURDIR}/../../sys/fs/autofs MAN= automount.8 automountd.8 autounmountd.8 auto_master.5 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util # Needed for getmntopts.c MOUNT= ${.CURDIR}/../../sbin/mount diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index 377a2e668b33..5a1c2c6ceccc 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -4,7 +4,7 @@ PROG= bhyve -DEBUG_FLAGS= -g -O0 +DEBUG_FLAGS= -g -O0 MAN= bhyve.8 @@ -43,8 +43,7 @@ SRCS= \ .PATH: ${.CURDIR}/../../sys/amd64/vmm SRCS+= vmm_instruction_emul.c -DPADD= ${LIBVMMAPI} ${LIBMD} ${LIBUTIL} ${LIBPTHREAD} -LDADD= -lvmmapi -lmd -lutil -lpthread +LIBADD= vmmapi md util pthread WARNS?= 2 diff --git a/usr.sbin/bhyvectl/Makefile b/usr.sbin/bhyvectl/Makefile index 5f879fe79bee..4a33dee94676 100644 --- a/usr.sbin/bhyvectl/Makefile +++ b/usr.sbin/bhyvectl/Makefile @@ -7,8 +7,7 @@ SRCS= bhyvectl.c MAN= -DPADD= ${LIBVMMAPI} ${LIBUTIL} -LDADD= -lvmmapi -lutil +LIBADD= vmmapi util WARNS?= 3 diff --git a/usr.sbin/bhyveload/Makefile b/usr.sbin/bhyveload/Makefile index e7b19bd82883..aa89b6c16d91 100644 --- a/usr.sbin/bhyveload/Makefile +++ b/usr.sbin/bhyveload/Makefile @@ -4,8 +4,7 @@ PROG= bhyveload SRCS= bhyveload.c MAN= bhyveload.8 -DPADD+= ${LIBVMMAPI} ${LIBUTIL} -LDADD+= -lvmmapi -lutil +LIBADD= vmmapi util WARNS?= 3 diff --git a/usr.sbin/bluetooth/ath3kfw/Makefile b/usr.sbin/bluetooth/ath3kfw/Makefile index 373655b210dd..26ce06e71a88 100644 --- a/usr.sbin/bluetooth/ath3kfw/Makefile +++ b/usr.sbin/bluetooth/ath3kfw/Makefile @@ -2,7 +2,6 @@ PROG= ath3kfw MAN= ath3kfw.8 -DPADD+= ${LIBUSB} -LDADD+= -lusb +LIBADD+= usb .include diff --git a/usr.sbin/bluetooth/bt3cfw/Makefile b/usr.sbin/bluetooth/bt3cfw/Makefile index 90bf7517253e..f9da6cac05ab 100644 --- a/usr.sbin/bluetooth/bt3cfw/Makefile +++ b/usr.sbin/bluetooth/bt3cfw/Makefile @@ -5,7 +5,6 @@ PROG= bt3cfw MAN= bt3cfw.8 WARNS?= 2 -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD+= netgraph .include diff --git a/usr.sbin/bluetooth/bthidcontrol/Makefile b/usr.sbin/bluetooth/bthidcontrol/Makefile index 6c9eafb735c1..09128d6c0059 100644 --- a/usr.sbin/bluetooth/bthidcontrol/Makefile +++ b/usr.sbin/bluetooth/bthidcontrol/Makefile @@ -9,7 +9,6 @@ SRCS= bthidcontrol.c hid.c lexer.l parser.y sdp.c WARNS?= 1 CFLAGS+= -DBTHIDCONTROL=1 -I${.CURDIR}/../bthidd -DPADD= ${LIBBLUETOOTH} ${LIBSDP} ${LIBUSBHID} -LDADD= -lbluetooth -lsdp -lusbhid +LIBADD+= bluetooth sdp usbhid .include diff --git a/usr.sbin/bluetooth/bthidd/Makefile b/usr.sbin/bluetooth/bthidd/Makefile index fe6ef33ff179..587189bf00ee 100644 --- a/usr.sbin/bluetooth/bthidd/Makefile +++ b/usr.sbin/bluetooth/bthidd/Makefile @@ -10,8 +10,7 @@ SRCS= bthidd.c client.c hid.c kbd.c lexer.l parser.y server.c \ CFLAGS+= -I${.CURDIR} DEBUG_FLAGS= -g -DPADD= ${LIBBLUETOOTH} ${LIBUSBHID} -LDADD= -lbluetooth -lusbhid +LIBADD+= bluetooth usbhid NO_WMISSING_VARIABLE_DECLARATIONS= diff --git a/usr.sbin/bluetooth/btpand/Makefile b/usr.sbin/bluetooth/btpand/Makefile index 5e4bb0b71674..0689d17c6c31 100644 --- a/usr.sbin/bluetooth/btpand/Makefile +++ b/usr.sbin/bluetooth/btpand/Makefile @@ -7,7 +7,6 @@ SRCS= btpand.c bnep.c channel.c client.c event.c packet.c server.c sdp.c tap.c WARNS?= 3 -DPADD+= ${LIBBLUETOOTH} ${LIBSDP} ${LIBUTIL} -LDADD+= -lbluetooth -lsdp -lutil +LIBADD= bluetooth sdp util .include diff --git a/usr.sbin/bluetooth/hccontrol/Makefile b/usr.sbin/bluetooth/hccontrol/Makefile index 592247e11ad9..61206dfcbe47 100644 --- a/usr.sbin/bluetooth/hccontrol/Makefile +++ b/usr.sbin/bluetooth/hccontrol/Makefile @@ -8,7 +8,6 @@ SRCS= send_recv.c link_policy.c link_control.c \ util.c WARNS?= 2 -DPADD= ${LIBBLUETOOTH} -LDADD= -lbluetooth +LIBADD= bluetooth .include diff --git a/usr.sbin/bluetooth/hcsecd/Makefile b/usr.sbin/bluetooth/hcsecd/Makefile index e544ed4e6180..684243d8fd7b 100644 --- a/usr.sbin/bluetooth/hcsecd/Makefile +++ b/usr.sbin/bluetooth/hcsecd/Makefile @@ -7,7 +7,6 @@ SRCS= hcsecd.c lexer.l parser.y WARNS?= 2 CFLAGS+= -I${.CURDIR} -DPADD= ${LIBBLUETOOTH} -LDADD= -lbluetooth +LIBADD= bluetooth .include diff --git a/usr.sbin/bluetooth/hcseriald/Makefile b/usr.sbin/bluetooth/hcseriald/Makefile index ed0bf3243820..e02e1ae48b8a 100644 --- a/usr.sbin/bluetooth/hcseriald/Makefile +++ b/usr.sbin/bluetooth/hcseriald/Makefile @@ -5,7 +5,6 @@ PROG= hcseriald MAN= hcseriald.8 WARNS?= 2 -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph .include diff --git a/usr.sbin/bluetooth/l2control/Makefile b/usr.sbin/bluetooth/l2control/Makefile index 847ff4ba97d6..8f17e02f0045 100644 --- a/usr.sbin/bluetooth/l2control/Makefile +++ b/usr.sbin/bluetooth/l2control/Makefile @@ -6,7 +6,6 @@ MAN= l2control.8 SRCS= l2cap.c l2control.c WARNS?= 2 -DPADD= ${LIBBLUETOOTH} -LDADD= -lbluetooth +LIBADD= bluetooth .include diff --git a/usr.sbin/bluetooth/l2ping/Makefile b/usr.sbin/bluetooth/l2ping/Makefile index bc130e33aac9..572366ae4dd3 100644 --- a/usr.sbin/bluetooth/l2ping/Makefile +++ b/usr.sbin/bluetooth/l2ping/Makefile @@ -5,7 +5,6 @@ PROG= l2ping MAN= l2ping.8 WARNS?= 2 -DPADD= ${LIBBLUETOOTH} -LDADD= -lbluetooth +LIBADD= bluetooth .include diff --git a/usr.sbin/bluetooth/rfcomm_pppd/Makefile b/usr.sbin/bluetooth/rfcomm_pppd/Makefile index adac64eca14a..f31e1e518480 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/Makefile +++ b/usr.sbin/bluetooth/rfcomm_pppd/Makefile @@ -8,7 +8,6 @@ MAN= rfcomm_pppd.8 SRCS= rfcomm_pppd.c rfcomm_sdp.c WARNS?= 2 -DPADD= ${LIBBLUETOOTH} ${LIBSDP} -LDADD= -lbluetooth -lsdp +LIBADD= bluetooth sdp .include diff --git a/usr.sbin/bluetooth/sdpcontrol/Makefile b/usr.sbin/bluetooth/sdpcontrol/Makefile index c0ec8d423f74..e3ebcd8d7254 100644 --- a/usr.sbin/bluetooth/sdpcontrol/Makefile +++ b/usr.sbin/bluetooth/sdpcontrol/Makefile @@ -6,7 +6,6 @@ MAN= sdpcontrol.8 SRCS= sdpcontrol.c search.c WARNS?= 2 -DPADD= ${LIBBLUETOOTH} ${LIBSDP} -LDADD= -lbluetooth -lsdp +LIBADD= bluetooth sdp .include diff --git a/usr.sbin/boot0cfg/Makefile b/usr.sbin/boot0cfg/Makefile index bb7fe07907f1..d41945a655a9 100644 --- a/usr.sbin/boot0cfg/Makefile +++ b/usr.sbin/boot0cfg/Makefile @@ -3,8 +3,7 @@ PROG= boot0cfg MAN= boot0cfg.8 -DPADD= ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} -LDADD= -lgeom -lbsdxml -lsbuf +LIBADD= geom NO_WCAST_ALIGN= diff --git a/usr.sbin/boot98cfg/Makefile b/usr.sbin/boot98cfg/Makefile index 9b0e70316315..57dfe94c1f8b 100644 --- a/usr.sbin/boot98cfg/Makefile +++ b/usr.sbin/boot98cfg/Makefile @@ -5,7 +5,6 @@ MAN= boot98cfg.8 WARNS?= 2 -DPADD= ${LIBGEOM} -LDADD= -lgeom +LIBADD= geom .include diff --git a/usr.sbin/bsdinstall/distextract/Makefile b/usr.sbin/bsdinstall/distextract/Makefile index f84c4d744a37..464ef6bf3466 100644 --- a/usr.sbin/bsdinstall/distextract/Makefile +++ b/usr.sbin/bsdinstall/distextract/Makefile @@ -2,8 +2,7 @@ BINDIR= /usr/libexec/bsdinstall PROG= distextract -DPADD= ${LIBARCHIVE} ${LIBNCURSESW} ${LIBDIALOG} ${LIBM} -LDADD= -larchive -lncursesw -ldialog -lm +LIBADD= archive ncursesw dialog m WARNS?= 6 MAN= diff --git a/usr.sbin/bsdinstall/distfetch/Makefile b/usr.sbin/bsdinstall/distfetch/Makefile index ed1f5996ec58..5c0f6e826bc1 100644 --- a/usr.sbin/bsdinstall/distfetch/Makefile +++ b/usr.sbin/bsdinstall/distfetch/Makefile @@ -2,8 +2,7 @@ BINDIR= /usr/libexec/bsdinstall PROG= distfetch -DPADD= ${LIBFETCH} ${LIBNCURSESW} ${LIBDIALOG} ${LIBM} -LDADD= -lfetch -lncursesw -ldialog -lm +LIBADD= fetch ncursesw dialog m WARNS?= 6 MAN= diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile index fb758884a572..d48f777343eb 100644 --- a/usr.sbin/bsdinstall/partedit/Makefile +++ b/usr.sbin/bsdinstall/partedit/Makefile @@ -5,8 +5,7 @@ PROG= partedit LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \ ${BINDIR}/partedit ${BINDIR}/scriptedpart SYMLINKS= ${BINDIR}/partedit /usr/sbin/sade -DPADD= ${LIBGEOM} ${LIBNCURSESW} ${LIBUTIL} ${LIBDIALOG} ${LIBM} -LDADD= -lgeom -lncursesw -lutil -ldialog -lm +LIBADD+= geom ncursesw util dialog m PARTEDIT_ARCH= ${MACHINE} .if ${MACHINE} == "i386" || ${MACHINE} == "amd64" diff --git a/usr.sbin/bsnmpd/bsnmpd/Makefile b/usr.sbin/bsnmpd/bsnmpd/Makefile index b20ba31d604c..a426345325b7 100644 --- a/usr.sbin/bsnmpd/bsnmpd/Makefile +++ b/usr.sbin/bsnmpd/bsnmpd/Makefile @@ -29,8 +29,7 @@ CFLAGS+= -DSNMPTREE_TYPES CFLAGS+= -I${CONTRIB}/lib -I${CONTRIB}/snmpd -I. -DUSE_LIBBEGEMOT CFLAGS+= -DUSE_TCPWRAPPERS -DQUADFMT='"llu"' -DQUADXFMT='"llx"' CFLAGS+= -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DHAVE_ERR_H -DHAVE_STRLCPY -DPADD= ${LIBBEGEMOT} ${LIBBSNMP} ${LIBWRAP} -LDADD= -lbegemot -lbsnmp -lwrap +LIBADD= begemot bsnmp wrap LDFLAGS= -Wl,-export-dynamic diff --git a/usr.sbin/bsnmpd/modules/snmp_hast/Makefile b/usr.sbin/bsnmpd/modules/snmp_hast/Makefile index e05ce31020ed..d0c3a48f22b0 100644 --- a/usr.sbin/bsnmpd/modules/snmp_hast/Makefile +++ b/usr.sbin/bsnmpd/modules/snmp_hast/Makefile @@ -29,8 +29,7 @@ CFLAGS+=-DYY_NO_UNPUT CFLAGS+=-DYY_NO_INPUT CFLAGS+= -DSNMPTREE_TYPES -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util XSYM= begemotHast DEFS= ${MOD}_tree.def diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile b/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile index 2922f45aa8b1..57f3eab0d5f5 100644 --- a/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile +++ b/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile @@ -69,8 +69,7 @@ MAN= snmp_hostres.3 DEFS= ${MOD}_tree.def BMIBS= BEGEMOT-HOSTRES-MIB.txt -DPADD= ${LIBKVM} ${LIBDEVINFO} ${LIBM} ${LIBGEOM} ${LIBMEMSTAT} -LDADD= -lkvm -ldevinfo -lm -lgeom -lmemstat +LIBADD= kvm devinfo m geom memstat .include diff --git a/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile b/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile index 7caf7e40bbee..85057c96eb0a 100644 --- a/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile +++ b/usr.sbin/bsnmpd/modules/snmp_netgraph/Makefile @@ -11,7 +11,6 @@ BMIBS= BEGEMOT-NETGRAPH.txt DEFS= ${MOD}_tree.def INCS= snmp_${MOD}.h -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph .include diff --git a/usr.sbin/bsnmpd/tools/bsnmptools/Makefile b/usr.sbin/bsnmpd/tools/bsnmptools/Makefile index 3310420a4f38..49afd9484064 100644 --- a/usr.sbin/bsnmpd/tools/bsnmptools/Makefile +++ b/usr.sbin/bsnmpd/tools/bsnmptools/Makefile @@ -7,14 +7,11 @@ PROG= bsnmpget -DPADD+= ${LIBBSNMP} ${LIBBSNMPTOOLS} -LDADD+= -lbsnmp -lbsnmptools +LIBADD= bsnmp bsnmptools CFLAGS+= -I${.CURDIR}/../libbsnmptools -LDFLAGS+= -L${LIBBSNMPTOOLSDIR} .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto .endif LINKS= ${BINDIR}/bsnmpget ${BINDIR}/bsnmpwalk diff --git a/usr.sbin/cdcontrol/Makefile b/usr.sbin/cdcontrol/Makefile index fa0dc2c094cf..de9560644501 100644 --- a/usr.sbin/cdcontrol/Makefile +++ b/usr.sbin/cdcontrol/Makefile @@ -2,7 +2,6 @@ PROG= cdcontrol -DPADD= ${LIBEDIT} ${LIBTERMCAPW} -LDADD= -ledit -ltermcapw +LIBADD= edit .include diff --git a/usr.sbin/ckdist/Makefile b/usr.sbin/ckdist/Makefile index 23430a8bb1af..4d3576320c69 100644 --- a/usr.sbin/ckdist/Makefile +++ b/usr.sbin/ckdist/Makefile @@ -5,7 +5,6 @@ PROG= ckdist SRCS= ckdist.c crc.c -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md .include diff --git a/usr.sbin/clear_locks/Makefile b/usr.sbin/clear_locks/Makefile index 00ff3ce95adc..6906bf0c7e8a 100644 --- a/usr.sbin/clear_locks/Makefile +++ b/usr.sbin/clear_locks/Makefile @@ -2,7 +2,6 @@ PROG= clear_locks MAN= clear_locks.8 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc .include diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile index 656198963a06..76712d2861e1 100644 --- a/usr.sbin/config/Makefile +++ b/usr.sbin/config/Makefile @@ -13,8 +13,7 @@ CFLAGS+= -I. -I${.CURDIR} NO_WMISSING_VARIABLE_DECLARATIONS= -DPADD= ${LIBL} ${LIBSBUF} -LDADD= -ll -lsbuf +LIBADD= l sbuf CLEANFILES+= kernconf.c diff --git a/usr.sbin/cron/Makefile.inc b/usr.sbin/cron/Makefile.inc index 900730b2e943..265f86d1ed55 100644 --- a/usr.sbin/cron/Makefile.inc +++ b/usr.sbin/cron/Makefile.inc @@ -1,5 +1,3 @@ # $FreeBSD$ -LIBCRON= ${.OBJDIR}/../lib/libcron.a - .include "../Makefile.inc" diff --git a/usr.sbin/cron/cron/Makefile b/usr.sbin/cron/cron/Makefile index d9a1d247d41e..0aa84d8a26fd 100644 --- a/usr.sbin/cron/cron/Makefile +++ b/usr.sbin/cron/cron/Makefile @@ -6,8 +6,7 @@ SRCS= cron.c database.c do_command.c job.c user.c popen.c CFLAGS+= -DLOGIN_CAP -DPAM -DPADD= ${LIBCRON} ${LIBPAM} ${LIBUTIL} -LDADD= ${LIBCRON} ${MINUSLPAM} -lutil +LIBADD= cron pam util WARNS?= 2 diff --git a/usr.sbin/cron/crontab/Makefile b/usr.sbin/cron/crontab/Makefile index 829128e5729e..9f4311253ac8 100644 --- a/usr.sbin/cron/crontab/Makefile +++ b/usr.sbin/cron/crontab/Makefile @@ -12,7 +12,6 @@ WARNS?= 3 CFLAGS+= -I${.CURDIR}/../cron -DPADD= ${LIBCRON} ${LIBMD} ${LIBUTIL} -LDADD= ${LIBCRON} -lmd -lutil +LIBADD= cron md util .include diff --git a/usr.sbin/ctladm/Makefile b/usr.sbin/ctladm/Makefile index a9f6bfd81780..fd9e606af909 100644 --- a/usr.sbin/ctladm/Makefile +++ b/usr.sbin/ctladm/Makefile @@ -14,8 +14,7 @@ CFLAGS+= -I${SDIR} WARNS?= 3 .endif -DPADD= ${LIBCAM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL} -LDADD= -lcam -lsbuf -lbsdxml -lutil +LIBADD= cam sbuf bsdxml util MAN= ctladm.8 .include diff --git a/usr.sbin/ctld/Makefile b/usr.sbin/ctld/Makefile index 149ae397fad1..bd3fb940ae2e 100644 --- a/usr.sbin/ctld/Makefile +++ b/usr.sbin/ctld/Makefile @@ -10,8 +10,7 @@ CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi #CFLAGS+= -DICL_KERNEL_PROXY MAN= ctld.8 ctl.conf.5 -DPADD= ${LIBBSDXML} ${LIBCRYPTO} ${LIBL} ${LIBSBUF} ${LIBUTIL} -LDADD= -lbsdxml -lcrypto -ll -lsbuf -lutil +LIBADD= bsdxml crypto l sbuf util YFLAGS+= -v CLEANFILES= y.tab.c y.tab.h y.output diff --git a/usr.sbin/ctm/ctm/Makefile b/usr.sbin/ctm/ctm/Makefile index cc2c9b978e7b..dd27ed2e3a94 100644 --- a/usr.sbin/ctm/ctm/Makefile +++ b/usr.sbin/ctm/ctm/Makefile @@ -14,8 +14,7 @@ SRCS= ctm.c ctm_input.c ctm_pass1.c ctm_pass2.c ctm_pass3.c \ NOTYET= ctm_ed.c -LDADD= -lmd -DPADD= ${LIBMD} +LIBADD= md WARNS?= 2 diff --git a/usr.sbin/ctm/mkCTM/Makefile b/usr.sbin/ctm/mkCTM/Makefile index 745956cad61f..8194dd7f8278 100644 --- a/usr.sbin/ctm/mkCTM/Makefile +++ b/usr.sbin/ctm/mkCTM/Makefile @@ -3,8 +3,7 @@ PROG= mkctm MAN= -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md test: mkctm rm -f tst.out* diff --git a/usr.sbin/daemon/Makefile b/usr.sbin/daemon/Makefile index 2def8037f2a7..eb0d50280161 100644 --- a/usr.sbin/daemon/Makefile +++ b/usr.sbin/daemon/Makefile @@ -3,7 +3,6 @@ PROG= daemon MAN= daemon.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/dconschat/Makefile b/usr.sbin/dconschat/Makefile index 2836a6678d86..198c5cccafb6 100644 --- a/usr.sbin/dconschat/Makefile +++ b/usr.sbin/dconschat/Makefile @@ -5,8 +5,7 @@ MAN= dconschat.8 CFLAGS+= -I${.CURDIR}/../../sys -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm WARNS?= 1 diff --git a/usr.sbin/devinfo/Makefile b/usr.sbin/devinfo/Makefile index 2a2301bf545f..681c8197f5de 100644 --- a/usr.sbin/devinfo/Makefile +++ b/usr.sbin/devinfo/Makefile @@ -3,7 +3,6 @@ PROG= devinfo MAN= devinfo.8 -DPADD= ${LIBDEVINFO} -LDADD= -ldevinfo +LIBADD= devinfo .include diff --git a/usr.sbin/diskinfo/Makefile b/usr.sbin/diskinfo/Makefile index b16b9335c259..41c52da551be 100644 --- a/usr.sbin/diskinfo/Makefile +++ b/usr.sbin/diskinfo/Makefile @@ -3,8 +3,7 @@ PROG= diskinfo MAN= diskinfo.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/editmap/Makefile b/usr.sbin/editmap/Makefile index 92d8392bf1f8..20d86abd92a9 100644 --- a/usr.sbin/editmap/Makefile +++ b/usr.sbin/editmap/Makefile @@ -12,17 +12,7 @@ CFLAGS+= -DNEWDB -DNOT_SENDMAIL WARNS?= 2 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMDBDIR= ${.OBJDIR}/../../lib/libsmdb -LIBSMDB= ${LIBSMDBDIR}/libsmdb.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} -LDADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} +LIBADD= smdb smutil sm SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/usr.sbin/edquota/Makefile b/usr.sbin/edquota/Makefile index 1196e4721417..83f06d055270 100644 --- a/usr.sbin/edquota/Makefile +++ b/usr.sbin/edquota/Makefile @@ -7,7 +7,6 @@ MAN= edquota.8 CSTD= gnu99 WARNS?= 4 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/fifolog/Makefile.inc b/usr.sbin/fifolog/Makefile.inc index 5ec27ddb4247..265f86d1ed55 100644 --- a/usr.sbin/fifolog/Makefile.inc +++ b/usr.sbin/fifolog/Makefile.inc @@ -1,8 +1,3 @@ # $FreeBSD$ -LIBFIFOLOG= ${.OBJDIR}/../lib/libfifolog.a - -#LINT= flint -#LINTFLAGS= ${.CURDIR}/../flint.lnt -I/usr/include - .include "../Makefile.inc" diff --git a/usr.sbin/fifolog/fifolog_create/Makefile b/usr.sbin/fifolog/fifolog_create/Makefile index 8b59b25ed251..4a83b5be96f5 100644 --- a/usr.sbin/fifolog/fifolog_create/Makefile +++ b/usr.sbin/fifolog/fifolog_create/Makefile @@ -4,8 +4,7 @@ PROG= fifolog_create CFLAGS+= -I${.CURDIR}/../lib -DPADD= ${LIBFIFOLOG} ${LIBUTIL} -LDADD= ${LIBFIFOLOG} -lutil +LIBADD= util fifolog MAN= fifolog.1 MLINKS= fifolog.1 fifolog_create.1 \ diff --git a/usr.sbin/fifolog/fifolog_reader/Makefile b/usr.sbin/fifolog/fifolog_reader/Makefile index 50575a9fac18..19ce28144e07 100644 --- a/usr.sbin/fifolog/fifolog_reader/Makefile +++ b/usr.sbin/fifolog/fifolog_reader/Makefile @@ -6,8 +6,7 @@ CFLAGS+= -I${.CURDIR}/../lib MAN= -DPADD= ${LIBFIFOLOG} ${LIBZ} -LDADD= ${LIBFIFOLOG} -lz +LIBADD= z fifolog regress: ./${PROG} /tmp/fifolog.0 diff --git a/usr.sbin/fifolog/fifolog_writer/Makefile b/usr.sbin/fifolog/fifolog_writer/Makefile index 9806ec7217c9..3e5e6cc83224 100644 --- a/usr.sbin/fifolog/fifolog_writer/Makefile +++ b/usr.sbin/fifolog/fifolog_writer/Makefile @@ -6,8 +6,7 @@ CFLAGS+= -I${.CURDIR}/../lib MAN= -DPADD= ${LIBFIFOLOG} ${LIBZ} -LDADD= ${LIBFIFOLOG} -lz +LIBADD= z fifolog regress: date | ./${PROG} -z 0 /tmp/fifolog.0 diff --git a/usr.sbin/flowctl/Makefile b/usr.sbin/flowctl/Makefile index acee16ba8eff..8bd63893cc6a 100644 --- a/usr.sbin/flowctl/Makefile +++ b/usr.sbin/flowctl/Makefile @@ -8,8 +8,7 @@ PROG= flowctl MAN= flowctl.8 WARNS?= 2 -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 diff --git a/usr.sbin/ftp-proxy/Makefile b/usr.sbin/ftp-proxy/Makefile index 7a3ef477226c..103ea867985b 100644 --- a/usr.sbin/ftp-proxy/Makefile +++ b/usr.sbin/ftp-proxy/Makefile @@ -9,8 +9,7 @@ SRCS= ftp-proxy.c filter.c CFLAGS+=-I${.CURDIR}/../../contrib/pf/libevent -LDADD+= ${LIBEVENT} -DPADD+= ${LIBEVENT} +LIBADD= event WARNS?= 3 diff --git a/usr.sbin/gssd/Makefile b/usr.sbin/gssd/Makefile index 9573702b1b62..ddc1dfabb997 100644 --- a/usr.sbin/gssd/Makefile +++ b/usr.sbin/gssd/Makefile @@ -9,11 +9,9 @@ SRCS= gssd.c gssd.h gssd_svc.c gssd_xdr.c gssd_prot.c CFLAGS+= -I. WARNS?= 1 -DPADD= ${LIBGSSAPI} -LDADD= -lgssapi +LIBADD= gssapi .if ${MK_KERBEROS_SUPPORT} != "no" -DPADD+= ${LIBKRB5} ${LIBHX509} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR} ${LIBCRYPT} ${LIBCRYPTO} -LDADD+= -lkrb5 -lhx509 -lasn1 -lroken -lcom_err -lcrypt -lcrypto +LIBADD+= krb5 roken .else CFLAGS+= -DWITHOUT_KERBEROS .endif diff --git a/usr.sbin/gstat/Makefile b/usr.sbin/gstat/Makefile index 8aceec07d487..1c71f2285622 100644 --- a/usr.sbin/gstat/Makefile +++ b/usr.sbin/gstat/Makefile @@ -2,7 +2,6 @@ PROG= gstat MAN= gstat.8 -DPADD= ${LIBDEVSTAT} ${LIBKVM} ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} ${LIBEDIT} ${LIBNCURSESW} -LDADD= -ldevstat -lkvm -lgeom -lbsdxml -lsbuf -ledit -lncursesw +LIBADD= devstat geom edit ncursesw .include diff --git a/usr.sbin/ifmcstat/Makefile b/usr.sbin/ifmcstat/Makefile index 5b967c7b9eaf..20de277e2bf2 100644 --- a/usr.sbin/ifmcstat/Makefile +++ b/usr.sbin/ifmcstat/Makefile @@ -17,8 +17,7 @@ CFLAGS+=-DINET6 .if ${MK_KVM_SUPPORT} != "no" CFLAGS+=-DWITH_KVM -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm .endif .include diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile index f31027af8765..6174592b34bb 100644 --- a/usr.sbin/inetd/Makefile +++ b/usr.sbin/inetd/Makefile @@ -16,14 +16,12 @@ CFLAGS+= -DLOGIN_CAP CFLAGS+= -DINET6 .endif -DPADD= ${LIBUTIL} ${LIBWRAP} -LDADD= -lutil -lwrap +LIBADD= util wrap # XXX for src/release/picobsd .if !defined(RELEASE_CRUNCH) CFLAGS+= -DIPSEC -DPADD+= ${LIBIPSEC} -LDADD+= -lipsec +LIBADD+= ipsec .endif .include diff --git a/usr.sbin/iostat/Makefile b/usr.sbin/iostat/Makefile index 9fd4809a5455..dfbf69dc724c 100644 --- a/usr.sbin/iostat/Makefile +++ b/usr.sbin/iostat/Makefile @@ -4,8 +4,7 @@ PROG= iostat MAN= iostat.8 -DPADD= ${LIBDEVSTAT} ${LIBKVM} ${LIBM} -LDADD= -ldevstat -lkvm -lm +LIBADD= devstat kvm m WARNS?= 1 diff --git a/usr.sbin/ipfwpcap/Makefile b/usr.sbin/ipfwpcap/Makefile index d16f888c67a6..2fde8900a16c 100644 --- a/usr.sbin/ipfwpcap/Makefile +++ b/usr.sbin/ipfwpcap/Makefile @@ -6,8 +6,7 @@ PROG= ipfwpcap -LDADD= -lpcap -DPADD= ${LIBPCAP} +LIBADD= pcap MAN= ipfwpcap.8 diff --git a/usr.sbin/iscsid/Makefile b/usr.sbin/iscsid/Makefile index 784c2047b39d..e3c6dd1efd63 100644 --- a/usr.sbin/iscsid/Makefile +++ b/usr.sbin/iscsid/Makefile @@ -8,8 +8,7 @@ CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi #CFLAGS+= -DICL_KERNEL_PROXY MAN= iscsid.8 -DPADD= ${LIBCRYPTO} ${LIBUTIL} -LDADD= -lcrypto -lutil +LIBADD= crypto util WARNS= 6 diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile index 58324ac3c088..9dfdee59deb7 100644 --- a/usr.sbin/jail/Makefile +++ b/usr.sbin/jail/Makefile @@ -6,8 +6,7 @@ PROG= jail MAN= jail.8 jail.conf.5 SRCS= jail.c command.c config.c state.c jailp.h jaillex.l jailparse.y y.tab.h -DPADD= ${LIBJAIL} ${LIBKVM} ${LIBUTIL} ${LIBL} -LDADD= -ljail -lkvm -lutil -ll +LIBADD= jail kvm util l NO_WMISSING_VARIABLE_DECLARATIONS= diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c index 0d1c89857067..6101e078bc2c 100644 --- a/usr.sbin/jail/command.c +++ b/usr.sbin/jail/command.c @@ -260,8 +260,8 @@ run_command(struct cfjail *j) const struct passwd *pwd; const struct cfstring *comstring, *s; login_cap_t *lcap; - char **argv; - char *cs, *comcs, *devpath; + const char **argv; + char *acs, *cs, *comcs, *devpath; const char *jidstr, *conslog, *path, *ruleset, *term, *username; enum intparam comparam; size_t comlen; @@ -332,27 +332,26 @@ run_command(struct cfjail *j) } argv = alloca((8 + argc) * sizeof(char *)); - *(const char **)&argv[0] = _PATH_IFCONFIG; + argv[0] = _PATH_IFCONFIG; if ((cs = strchr(val, '|'))) { - argv[1] = alloca(cs - val + 1); - strlcpy(argv[1], val, cs - val + 1); + argv[1] = acs = alloca(cs - val + 1); + strlcpy(acs, val, cs - val + 1); addr = cs + 1; } else { - *(const char **)&argv[1] = - string_param(j->intparams[IP_INTERFACE]); + argv[1] = string_param(j->intparams[IP_INTERFACE]); addr = val; } - *(const char **)&argv[2] = "inet"; + argv[2] = "inet"; if (!(cs = strchr(addr, '/'))) { argv[3] = addr; - *(const char **)&argv[4] = "netmask"; - *(const char **)&argv[5] = "255.255.255.255"; + argv[4] = "netmask"; + argv[5] = "255.255.255.255"; argc = 6; } else if (strchr(cs + 1, '.')) { - argv[3] = alloca(cs - addr + 1); - strlcpy(argv[3], addr, cs - addr + 1); - *(const char **)&argv[4] = "netmask"; - *(const char **)&argv[5] = cs + 1; + argv[3] = acs = alloca(cs - addr + 1); + strlcpy(acs, addr, cs - addr + 1); + argv[4] = "netmask"; + argv[5] = cs + 1; argc = 6; } else { argv[3] = addr; @@ -360,14 +359,15 @@ run_command(struct cfjail *j) } if (!down) { - for (cs = strtok(extrap, " "); cs; cs = strtok(NULL, " ")) { + for (cs = strtok(extrap, " "); cs; + cs = strtok(NULL, " ")) { size_t len = strlen(cs) + 1; - argv[argc] = alloca(len); - strlcpy(argv[argc++], cs, len); + argv[argc++] = acs = alloca(len); + strlcpy(acs, cs, len); } } - *(const char **)&argv[argc] = down ? "-alias" : "alias"; + argv[argc] = down ? "-alias" : "alias"; argv[argc + 1] = NULL; break; #endif @@ -389,46 +389,45 @@ run_command(struct cfjail *j) } argv = alloca((8 + argc) * sizeof(char *)); - *(const char **)&argv[0] = _PATH_IFCONFIG; + argv[0] = _PATH_IFCONFIG; if ((cs = strchr(val, '|'))) { - argv[1] = alloca(cs - val + 1); - strlcpy(argv[1], val, cs - val + 1); + argv[1] = acs = alloca(cs - val + 1); + strlcpy(acs, val, cs - val + 1); addr = cs + 1; } else { - *(const char **)&argv[1] = - string_param(j->intparams[IP_INTERFACE]); + argv[1] = string_param(j->intparams[IP_INTERFACE]); addr = val; } - *(const char **)&argv[2] = "inet6"; + argv[2] = "inet6"; argv[3] = addr; if (!(cs = strchr(addr, '/'))) { - *(const char **)&argv[4] = "prefixlen"; - *(const char **)&argv[5] = "128"; + argv[4] = "prefixlen"; + argv[5] = "128"; argc = 6; } else argc = 4; if (!down) { - for (cs = strtok(extrap, " "); cs; cs = strtok(NULL, " ")) { + for (cs = strtok(extrap, " "); cs; + cs = strtok(NULL, " ")) { size_t len = strlen(cs) + 1; - argv[argc] = alloca(len); - strlcpy(argv[argc++], cs, len); + argv[argc++] = acs = alloca(len); + strlcpy(acs, cs, len); } } - *(const char **)&argv[argc] = down ? "-alias" : "alias"; + argv[argc] = down ? "-alias" : "alias"; argv[argc + 1] = NULL; break; #endif case IP_VNET_INTERFACE: argv = alloca(5 * sizeof(char *)); - *(const char **)&argv[0] = _PATH_IFCONFIG; + argv[0] = _PATH_IFCONFIG; argv[1] = comstring->s; - *(const char **)&argv[2] = down ? "-vnet" : "vnet"; + argv[2] = down ? "-vnet" : "vnet"; jidstr = string_param(j->intparams[KP_JID]); - *(const char **)&argv[3] = - jidstr ? jidstr : string_param(j->intparams[KP_NAME]); + argv[3] = jidstr ? jidstr : string_param(j->intparams[KP_NAME]); argv[4] = NULL; break; @@ -454,22 +453,22 @@ run_command(struct cfjail *j) if (down) { argv[4] = NULL; argv[3] = argv[1]; - *(const char **)&argv[0] = "/sbin/umount"; + argv[0] = "/sbin/umount"; } else { if (argc == 4) { argv[7] = NULL; argv[6] = argv[1]; argv[5] = argv[0]; argv[4] = argv[3]; - *(const char **)&argv[3] = "-o"; + argv[3] = "-o"; } else { argv[5] = NULL; argv[4] = argv[1]; argv[3] = argv[0]; } - *(const char **)&argv[0] = _PATH_MOUNT; + argv[0] = _PATH_MOUNT; } - *(const char **)&argv[1] = "-t"; + argv[1] = "-t"; break; case IP_MOUNT_DEVFS: @@ -485,19 +484,19 @@ run_command(struct cfjail *j) down ? "devfs" : NULL) < 0) return -1; if (down) { - *(const char **)&argv[0] = "/sbin/umount"; + argv[0] = "/sbin/umount"; argv[1] = devpath; argv[2] = NULL; } else { - *(const char **)&argv[0] = _PATH_MOUNT; - *(const char **)&argv[1] = "-t"; - *(const char **)&argv[2] = "devfs"; + argv[0] = _PATH_MOUNT; + argv[1] = "-t"; + argv[2] = "devfs"; ruleset = string_param(j->intparams[KP_DEVFS_RULESET]); if (!ruleset) ruleset = "4"; /* devfsrules_jail */ - argv[3] = alloca(11 + strlen(ruleset)); - sprintf(argv[3], "-oruleset=%s", ruleset); - *(const char **)&argv[4] = "."; + argv[3] = acs = alloca(11 + strlen(ruleset)); + sprintf(acs, "-oruleset=%s", ruleset); + argv[4] = "."; argv[5] = devpath; argv[6] = NULL; } @@ -516,14 +515,14 @@ run_command(struct cfjail *j) down ? "fdescfs" : NULL) < 0) return -1; if (down) { - *(const char **)&argv[0] = "/sbin/umount"; + argv[0] = "/sbin/umount"; argv[1] = devpath; argv[2] = NULL; } else { - *(const char **)&argv[0] = _PATH_MOUNT; - *(const char **)&argv[1] = "-t"; - *(const char **)&argv[2] = "fdescfs"; - *(const char **)&argv[3] = "."; + argv[0] = _PATH_MOUNT; + argv[1] = "-t"; + argv[2] = "fdescfs"; + argv[3] = "."; argv[4] = devpath; argv[5] = NULL; } @@ -548,8 +547,8 @@ run_command(struct cfjail *j) if ((cs = strpbrk(comstring->s, "!\"$&'()*;<>?[\\]`{|}~")) && !(cs[0] == '&' && cs[1] == '\0')) { argv = alloca(4 * sizeof(char *)); - *(const char **)&argv[0] = _PATH_BSHELL; - *(const char **)&argv[1] = "-c"; + argv[0] = _PATH_BSHELL; + argv[1] = "-c"; argv[2] = comstring->s; argv[3] = NULL; } else { @@ -693,7 +692,7 @@ run_command(struct cfjail *j) exit(1); } closefrom(3); - execvp(argv[0], argv); + execvp(argv[0], __DECONST(char *const*, argv)); jail_warnx(j, "exec %s: %s", argv[0], strerror(errno)); exit(1); } diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c index 661c4adfc660..b8f57793d868 100644 --- a/usr.sbin/jail/jail.c +++ b/usr.sbin/jail/jail.c @@ -656,11 +656,11 @@ create_jail(struct cfjail *j) * The jail already exists, but may be dying. * Make sure it is, in which case an update is appropriate. */ - *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_base = __DECONST(char *, "jid"); jiov[0].iov_len = sizeof("jid"); jiov[1].iov_base = &jid; jiov[1].iov_len = sizeof(jid); - *(const void **)&jiov[2].iov_base = "dying"; + jiov[2].iov_base = __DECONST(char *, "dying"); jiov[2].iov_len = sizeof("dying"); jiov[3].iov_base = &dying; jiov[3].iov_len = sizeof(dying); @@ -721,11 +721,11 @@ clear_persist(struct cfjail *j) if (!(j->flags & JF_PERSIST)) return; j->flags &= ~JF_PERSIST; - *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_base = __DECONST(char *, "jid"); jiov[0].iov_len = sizeof("jid"); jiov[1].iov_base = &j->jid; jiov[1].iov_len = sizeof(j->jid); - *(const void **)&jiov[2].iov_base = "nopersist"; + jiov[2].iov_base = __DECONST(char *, "nopersist"); jiov[2].iov_len = sizeof("nopersist"); jiov[3].iov_base = NULL; jiov[3].iov_len = 0; @@ -849,12 +849,12 @@ running_jid(struct cfjail *j, int dflag) j->jid = -1; return; } - *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_base = __DECONST(char *, "jid"); jiov[0].iov_len = sizeof("jid"); jiov[1].iov_base = &jid; jiov[1].iov_len = sizeof(jid); } else if ((pval = string_param(j->intparams[KP_NAME]))) { - *(const void **)&jiov[0].iov_base = "name"; + jiov[0].iov_base = __DECONST(char *, "name"); jiov[0].iov_len = sizeof("name"); jiov[1].iov_len = strlen(pval) + 1; jiov[1].iov_base = alloca(jiov[1].iov_len); @@ -880,7 +880,7 @@ jail_quoted_warnx(const struct cfjail *j, const char *name_msg, } /* - * Set jail parameters and possible print them out. + * Set jail parameters and possibly print them out. */ static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp, diff --git a/usr.sbin/jail/state.c b/usr.sbin/jail/state.c index 17b2a0c266a2..b3eb9424fce1 100644 --- a/usr.sbin/jail/state.c +++ b/usr.sbin/jail/state.c @@ -60,7 +60,7 @@ dep_setup(int docf) const char *cs; char *pname; size_t plen; - int error, deps, ldeps; + int deps, ldeps; if (!docf) { /* @@ -88,7 +88,6 @@ dep_setup(int docf) TAILQ_FOREACH(j, &cfjails, tq) jails_byname[njails++] = j; qsort(jails_byname, njails, sizeof(struct cfjail *), cmp_jailptr); - error = 0; deps = 0; ldeps = 0; plen = 0; @@ -331,15 +330,15 @@ start_state(const char *target, int docf, unsigned state, int running) * -R matches its wildcards against currently running * jails, not against the config file. */ - *(const void **)&jiov[0].iov_base = "lastjid"; + jiov[0].iov_base = __DECONST(char *, "lastjid"); jiov[0].iov_len = sizeof("lastjid"); jiov[1].iov_base = &jid; jiov[1].iov_len = sizeof(jid); - *(const void **)&jiov[2].iov_base = "jid"; + jiov[2].iov_base = __DECONST(char *, "jid"); jiov[2].iov_len = sizeof("jid"); jiov[3].iov_base = &jid; jiov[3].iov_len = sizeof(jid); - *(const void **)&jiov[4].iov_base = "name"; + jiov[4].iov_base = __DECONST(char *, "name"); jiov[4].iov_len = sizeof("name"); jiov[5].iov_base = &namebuf; jiov[5].iov_len = sizeof(namebuf); @@ -454,12 +453,12 @@ running_jid(const char *name, int flags) int jid; if ((jid = strtol(name, &ep, 10)) && !*ep) { - *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_base = __DECONST(char *, "jid"); jiov[0].iov_len = sizeof("jid"); jiov[1].iov_base = &jid; jiov[1].iov_len = sizeof(jid); } else { - *(const void **)&jiov[0].iov_base = "name"; + jiov[0].iov_base = __DECONST(char *, "name"); jiov[0].iov_len = sizeof("name"); jiov[1].iov_len = strlen(name) + 1; jiov[1].iov_base = alloca(jiov[1].iov_len); diff --git a/usr.sbin/jexec/Makefile b/usr.sbin/jexec/Makefile index 7a2e6821e42a..700da973904a 100644 --- a/usr.sbin/jexec/Makefile +++ b/usr.sbin/jexec/Makefile @@ -2,7 +2,6 @@ PROG= jexec MAN= jexec.8 -DPADD= ${LIBJAIL} ${LIBUTIL} -LDADD= -ljail -lutil +LIBADD= jail util .include diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile index 431fd0c80c1d..d90d094a71e5 100644 --- a/usr.sbin/jls/Makefile +++ b/usr.sbin/jls/Makefile @@ -4,8 +4,7 @@ PROG= jls MAN= jls.8 -DPADD= ${LIBJAIL} -LDADD= -ljail +LIBADD= jail .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 diff --git a/usr.sbin/kbdcontrol/Makefile b/usr.sbin/kbdcontrol/Makefile index ca1b6e697bd4..42fa3e85a70a 100644 --- a/usr.sbin/kbdcontrol/Makefile +++ b/usr.sbin/kbdcontrol/Makefile @@ -8,7 +8,6 @@ SRCS= kbdcontrol.c lex.l WARNS?= 4 CFLAGS+= -I${.CURDIR} -DPADD= ${LIBL} -LDADD= -ll +LIBADD= l .include diff --git a/usr.sbin/keyserv/Makefile b/usr.sbin/keyserv/Makefile index 4308b40f2020..db8a8325dc6a 100644 --- a/usr.sbin/keyserv/Makefile +++ b/usr.sbin/keyserv/Makefile @@ -6,8 +6,7 @@ SRCS= keyserv.c setkey.c crypt_svc.c crypt_server.c crypt.h CFLAGS+= -DKEYSERV_RANDOM -DBROKEN_DES -I. -DPADD= ${LIBMP} ${LIBCRYPTO} ${LIBRPCSVC} -LDADD= -lmp -lcrypto -lrpcsvc +LIBADD= mp rpcsvc WARNS?= 1 diff --git a/usr.sbin/kgmon/Makefile b/usr.sbin/kgmon/Makefile index bf19401b494d..5f6a2a37950a 100644 --- a/usr.sbin/kgmon/Makefile +++ b/usr.sbin/kgmon/Makefile @@ -11,7 +11,6 @@ WARNS?= 2 #BINOWN=root #BINMODE=4555 -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm .include diff --git a/usr.sbin/lmcconfig/Makefile b/usr.sbin/lmcconfig/Makefile index 1ff5055ea32e..be00544600e5 100644 --- a/usr.sbin/lmcconfig/Makefile +++ b/usr.sbin/lmcconfig/Makefile @@ -3,8 +3,7 @@ PROG= lmcconfig MAN= lmcconfig.8 -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph WARNS?= 3 diff --git a/usr.sbin/lpr/Makefile.inc b/usr.sbin/lpr/Makefile.inc index 65535e6abac0..59f8ceb1ed55 100644 --- a/usr.sbin/lpr/Makefile.inc +++ b/usr.sbin/lpr/Makefile.inc @@ -6,6 +6,4 @@ CFLAGS+= -DINET6 .endif -LIBLPR= ${.OBJDIR}/../common_source/liblpr.a - .include "../Makefile.inc" diff --git a/usr.sbin/lpr/chkprintcap/Makefile b/usr.sbin/lpr/chkprintcap/Makefile index ffffffbb2bd1..aa08882b1076 100644 --- a/usr.sbin/lpr/chkprintcap/Makefile +++ b/usr.sbin/lpr/chkprintcap/Makefile @@ -8,7 +8,6 @@ SRCS= chkprintcap.c skimprintcap.c CFLAGS+= -I${.CURDIR}/../common_source -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/lpr/lpc/Makefile b/usr.sbin/lpr/lpc/Makefile index 92ca9e8faf46..43f1f7a71f6b 100644 --- a/usr.sbin/lpr/lpc/Makefile +++ b/usr.sbin/lpr/lpc/Makefile @@ -5,7 +5,7 @@ PROG= lpc MAN= lpc.8 -SRCS= lpc.c cmds.c cmdtab.c movejobs.c +SRCS= lpc.c cmds.c cmdtab.c movejobs.c BINGRP= daemon BINMODE= 2555 @@ -13,7 +13,6 @@ CFLAGS+= -I${.CURDIR}/../common_source WARNS?= 0 -DPADD= ${LIBLPR} ${LIBEDIT} ${LIBTERMCAPW} -LDADD= ${LIBLPR} -ledit -ltermcapw +LIBADD= lpr edit .include diff --git a/usr.sbin/lpr/lpd/Makefile b/usr.sbin/lpr/lpd/Makefile index 0d7d93ef79d9..a35212bb2cc8 100644 --- a/usr.sbin/lpr/lpd/Makefile +++ b/usr.sbin/lpr/lpd/Makefile @@ -9,7 +9,6 @@ CFLAGS+= -I${.CURDIR}/../common_source WARNS?= 1 -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/lpr/lpq/Makefile b/usr.sbin/lpr/lpq/Makefile index 4df437e06c32..7ea22fa4cd4d 100644 --- a/usr.sbin/lpr/lpq/Makefile +++ b/usr.sbin/lpr/lpq/Makefile @@ -10,7 +10,6 @@ BINMODE= 6555 CFLAGS+= -I${.CURDIR}/../common_source -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/lpr/lpr/Makefile b/usr.sbin/lpr/lpr/Makefile index 1894b0089c04..2841a79290eb 100644 --- a/usr.sbin/lpr/lpr/Makefile +++ b/usr.sbin/lpr/lpr/Makefile @@ -15,7 +15,6 @@ CFLAGS+= -I${.CURDIR}/../common_source WARNS?= 2 -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/lpr/lprm/Makefile b/usr.sbin/lpr/lprm/Makefile index 44bc93ac27ec..5724d53280e3 100644 --- a/usr.sbin/lpr/lprm/Makefile +++ b/usr.sbin/lpr/lprm/Makefile @@ -12,7 +12,6 @@ BINMODE= 6555 CFLAGS+= -I${.CURDIR}/../common_source -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/lpr/pac/Makefile b/usr.sbin/lpr/pac/Makefile index bd895a71a305..faf8e581c3b9 100644 --- a/usr.sbin/lpr/pac/Makefile +++ b/usr.sbin/lpr/pac/Makefile @@ -8,7 +8,6 @@ MAN= pac.8 CFLAGS+= -I${.CURDIR}/../common_source -DPADD= ${LIBLPR} -LDADD= ${LIBLPR} +LIBADD= lpr .include diff --git a/usr.sbin/mailstats/Makefile b/usr.sbin/mailstats/Makefile index bd72fc6c5b76..a7911a272f25 100644 --- a/usr.sbin/mailstats/Makefile +++ b/usr.sbin/mailstats/Makefile @@ -13,14 +13,7 @@ CFLAGS+= -DNOT_SENDMAIL WARNS?= 2 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD= ${LIBSMUTIL} ${LIBSM} -LDADD= ${LIBSMUTIL} ${LIBSM} +LIBADD= sm smutil SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/usr.sbin/mailwrapper/Makefile b/usr.sbin/mailwrapper/Makefile index 8e49db7edd55..584cab895523 100644 --- a/usr.sbin/mailwrapper/Makefile +++ b/usr.sbin/mailwrapper/Makefile @@ -6,8 +6,7 @@ PROG= mailwrapper MAN= mailwrapper.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .endif .if ${MK_MAILWRAPPER} != "no" || ${MK_SENDMAIL} != "no" diff --git a/usr.sbin/makefs/Makefile b/usr.sbin/makefs/Makefile index 62531488128e..882fe4569c74 100644 --- a/usr.sbin/makefs/Makefile +++ b/usr.sbin/makefs/Makefile @@ -30,12 +30,6 @@ SRCS+= pack_dev.c SRCS+= ffs_tables.c CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd -LIBNETBSDDIR= ${.OBJDIR}/../../lib/libnetbsd -LIBNETBSD= ${LIBNETBSDDIR}/libnetbsd.a -DPADD+= ${LIBNETBSD} -LDADD+= ${LIBNETBSD} - -DPADD+= ${LIBSBUF} ${LIBUTIL} -LDADD+= -lsbuf -lutil +LIBADD= netbsd util sbuf .include diff --git a/usr.sbin/makemap/Makefile b/usr.sbin/makemap/Makefile index 80cafcbcfdba..ceec1b3d878b 100644 --- a/usr.sbin/makemap/Makefile +++ b/usr.sbin/makemap/Makefile @@ -13,17 +13,7 @@ CFLAGS+= -DNEWDB -DNOT_SENDMAIL WARNS?= 2 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMDBDIR= ${.OBJDIR}/../../lib/libsmdb -LIBSMDB= ${LIBSMDBDIR}/libsmdb.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} -LDADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} +LIBADD= sm smdb smutil SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile index 4fe6f0345222..dc6f3e481593 100644 --- a/usr.sbin/mfiutil/Makefile +++ b/usr.sbin/mfiutil/Makefile @@ -8,8 +8,7 @@ MAN8= mfiutil.8 CFLAGS.gcc+= -fno-builtin-strftime -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util # Here be dragons .ifdef DEBUG diff --git a/usr.sbin/mount_smbfs/Makefile b/usr.sbin/mount_smbfs/Makefile index bbc084fc9985..c4c2d1c79ef3 100644 --- a/usr.sbin/mount_smbfs/Makefile +++ b/usr.sbin/mount_smbfs/Makefile @@ -8,8 +8,7 @@ MOUNTDIR= ${.CURDIR}/../../sbin/mount CONTRIBDIR= ${.CURDIR}/../../contrib/smbfs CFLAGS+= -DSMBFS -I${MOUNTDIR} -I${CONTRIBDIR}/include -LDADD= -lsmb -lkiconv -DPADD= ${LIBSMB} ${LIBKICONV} +LIBADD= smb .PATH: ${CONTRIBDIR}/mount_smbfs .PATH: ${MOUNTDIR} diff --git a/usr.sbin/mountd/Makefile b/usr.sbin/mountd/Makefile index c141d8a0c8d0..ab32fa38e45d 100644 --- a/usr.sbin/mountd/Makefile +++ b/usr.sbin/mountd/Makefile @@ -11,7 +11,6 @@ WARNS?= 2 .PATH: ${MOUNT} -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/moused/Makefile b/usr.sbin/moused/Makefile index a313a213ac80..0f9eac5b2417 100644 --- a/usr.sbin/moused/Makefile +++ b/usr.sbin/moused/Makefile @@ -3,8 +3,7 @@ PROG= moused MAN= moused.8 -DPADD= ${LIBUTIL} ${LIBM} -LDADD= -lutil -lm +LIBADD= m util #BINMODE=4555 #PRECIOUSPROG= diff --git a/usr.sbin/mptutil/Makefile b/usr.sbin/mptutil/Makefile index 53d75b34d3d6..2054c26c5649 100644 --- a/usr.sbin/mptutil/Makefile +++ b/usr.sbin/mptutil/Makefile @@ -8,8 +8,7 @@ MAN= mptutil.8 WARNS?= 3 -DPADD= ${LIBCAM} ${LIBSBUF} ${LIBUTIL} -LDADD= -lcam -lsbuf -lutil +LIBADD= cam util # Here be dragons .ifdef DEBUG diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile index 1ceb52eeb6f5..4f23a7561076 100644 --- a/usr.sbin/mtree/Makefile +++ b/usr.sbin/mtree/Makefile @@ -11,8 +11,7 @@ SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c SRCS+= specspec.c CFLAGS+= -DMD5 -DSHA1 -DRMD160 -DSHA256 -DPADD= ${LIBMD} -LDADD= -lmd +LIBADD= md CLEANFILES+= fmtree.8 diff --git a/usr.sbin/nandtool/Makefile b/usr.sbin/nandtool/Makefile index ae9de2dcf4f4..c01c2fdedbbf 100644 --- a/usr.sbin/nandtool/Makefile +++ b/usr.sbin/nandtool/Makefile @@ -4,8 +4,7 @@ PROG= nandtool SRCS= nandtool.c nand_read.c nand_write.c nand_erase.c nand_info.c SRCS+= nand_readoob.c nand_writeoob.c BINDIR= /usr/sbin -DPADD= ${LIBGEOM} -LDADD= -lgeom +LIBADD= geom MAN= nandtool.8 .include diff --git a/usr.sbin/ndiscvt/Makefile b/usr.sbin/ndiscvt/Makefile index b11b4b07c1e5..3322a533f985 100644 --- a/usr.sbin/ndiscvt/Makefile +++ b/usr.sbin/ndiscvt/Makefile @@ -13,8 +13,7 @@ MAN+= ndisgen.8 WARNS?= 4 NO_WCAST_ALIGN= -DPADD= ${LIBL} -LDADD= -ll +LIBADD= l YFLAGS+=-v diff --git a/usr.sbin/ngctl/Makefile b/usr.sbin/ngctl/Makefile index cf72f39a6644..71b5d2b9dfaf 100644 --- a/usr.sbin/ngctl/Makefile +++ b/usr.sbin/ngctl/Makefile @@ -17,13 +17,11 @@ NGCTL_NO_LIBEDIT= NGCTL_NO_LIBEDIT= .endif -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph .if !defined(NGCTL_NO_LIBEDIT) CFLAGS+= -DEDITLINE -DPADD+= ${LIBPTHREAD} ${LIBEDIT} ${LIBTERMCAPW} -LDADD+= -lpthread -ledit -ltermcapw +LIBADD+= edit pthread .endif .include diff --git a/usr.sbin/nghook/Makefile b/usr.sbin/nghook/Makefile index e427f2603cc9..8a63d8238e17 100644 --- a/usr.sbin/nghook/Makefile +++ b/usr.sbin/nghook/Makefile @@ -5,7 +5,6 @@ PROG= nghook MAN= nghook.8 SRCS= main.c -DPADD= ${LIBNETGRAPH} -LDADD= -lnetgraph +LIBADD= netgraph .include diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile index 5789ad8bfc29..03af6d61ee3b 100644 --- a/usr.sbin/nmtree/Makefile +++ b/usr.sbin/nmtree/Makefile @@ -8,18 +8,13 @@ PROG= mtree MAN= mtree.5 mtree.8 SRCS= compare.c crc.c create.c excludes.c getid.c misc.c mtree.c \ only.c spec.c specspec.c verify.c -DPADD+= ${LIBMD} ${LIBUTIL} -LDADD+= -lmd -lutil CFLAGS+= -I${.CURDIR}/../../contrib/mknod .PATH: ${.CURDIR}/../../contrib/mknod SRCS+= pack_dev.c CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd -LIBNETBSDDIR= ${.OBJDIR}/../../lib/libnetbsd -LIBNETBSD= ${LIBNETBSDDIR}/libnetbsd.a -DPADD+= ${LIBNETBSD} -LDADD+= ${LIBNETBSD} +LIBADD= netbsd md util LINKS= ${BINDIR}/mtree ${BINDIR}/nmtree MLINKS= mtree.8 nmtree.8 diff --git a/usr.sbin/nscd/Makefile b/usr.sbin/nscd/Makefile index 298e163aec41..96a2e8a8f457 100644 --- a/usr.sbin/nscd/Makefile +++ b/usr.sbin/nscd/Makefile @@ -8,8 +8,8 @@ SRCS= agent.c nscd.c nscdcli.c cachelib.c cacheplcs.c debug.c log.c \ config.c query.c mp_ws_query.c mp_rs_query.c singletons.c protocol.c \ parser.c CFLAGS+= -DCONFIG_PATH="\"${PREFIX}/etc/nscd.conf\"" -DPADD= ${LIBM} ${LIBPTHREAD} ${LIBUTIL} -LDADD= -lm -lpthread -lutil + +LIBADD= util pthread .PATH: ${.CURDIR}/agents .include "${.CURDIR}/agents/Makefile.inc" diff --git a/usr.sbin/ntp/Makefile.inc b/usr.sbin/ntp/Makefile.inc index cadd4c7a941c..755fbee77c84 100644 --- a/usr.sbin/ntp/Makefile.inc +++ b/usr.sbin/ntp/Makefile.inc @@ -14,10 +14,6 @@ CFLAGS+= ${NTPDEFS} ${DEFS_LOCAL} ${CLOCKDEFS} CFLAGS+= -DOPENSSL .endif -LIBOPTS= ${.OBJDIR}/../libopts/libopts.a -LIBPARSE= ${.OBJDIR}/../libparse/libparse.a -LIBNTP= ${.OBJDIR}/../libntp/libntp.a - WARNS?= 0 .include "../Makefile.inc" diff --git a/usr.sbin/ntp/ntp-keygen/Makefile b/usr.sbin/ntp/ntp-keygen/Makefile index 78308fae0ac8..4091b8921cce 100644 --- a/usr.sbin/ntp/ntp-keygen/Makefile +++ b/usr.sbin/ntp/ntp-keygen/Makefile @@ -13,12 +13,10 @@ SRCS= ntp-keygen.c ntp-keygen-opts.c CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \ -I${.CURDIR}/../../../contrib/ntp/libopts -DPADD= ${LIBNTP} ${LIBOPTS} -LDADD= ${LIBNTP} ${LIBOPTS} +LIBADD+= ntp opts .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBMD} ${LIBCRYPTO} -LDADD+= -lmd -lcrypto +LIBADD+= md crypto .endif .include diff --git a/usr.sbin/ntp/ntpd/Makefile b/usr.sbin/ntp/ntpd/Makefile index 87b2d72b8544..58f35dee5cc5 100644 --- a/usr.sbin/ntp/ntpd/Makefile +++ b/usr.sbin/ntp/ntpd/Makefile @@ -32,12 +32,10 @@ SRCS= cmd_args.c ntp_config.c \ CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \ -I${.CURDIR}/../../../contrib/ntp/libopts -I${.CURDIR} -DPADD= ${LIBPARSE} ${LIBNTP} ${LIBM} ${LIBMD} ${LIBRT} ${LIBOPTS} -LDADD= ${LIBPARSE} ${LIBNTP} -lm -lmd -lrt ${LIBOPTS} +LIBADD= parse ntp m rt opts md .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto .endif CLEANFILES+= .version version.c diff --git a/usr.sbin/ntp/ntpdate/Makefile b/usr.sbin/ntp/ntpdate/Makefile index f55ec92bc5d9..7a45835e7662 100644 --- a/usr.sbin/ntp/ntpdate/Makefile +++ b/usr.sbin/ntp/ntpdate/Makefile @@ -8,8 +8,7 @@ SRCS= ntpdate.c version.c CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ -DPADD= ${LIBNTP} ${LIBM} ${LIBMD} ${LIBRT} -LDADD= ${LIBNTP} -lm -lmd -lrt +LIBADD= md rt ntp CLEANFILES+= .version version.c diff --git a/usr.sbin/ntp/ntpdc/Makefile b/usr.sbin/ntp/ntpdc/Makefile index d3c37e1b8fcb..cda51d45191f 100644 --- a/usr.sbin/ntp/ntpdc/Makefile +++ b/usr.sbin/ntp/ntpdc/Makefile @@ -12,11 +12,7 @@ SRCS= ntpdc.c ntpdc_ops.c ntpdc-opts.c version.c CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \ -I${.CURDIR}/../../../contrib/ntp/libopts -DPADD= ${LIBNTP} ${LIBM} ${LIBMD} ${LIBOPTS} -LDADD= ${LIBNTP} -lm -lmd ${LIBOPTS} - -DPADD+= ${LIBEDIT} ${LIBTERMCAPW} -LDADD+= -ledit -ltermcapw +LIBADD= edit md ntp opts CFLAGS+= -DHAVE_LIBEDIT -DHAVE_READLINE_READLINE_H \ -I${DESTDIR}/${INCLUDEDIR}/edit diff --git a/usr.sbin/ntp/ntpq/Makefile b/usr.sbin/ntp/ntpq/Makefile index 369bd588e12e..95e3296b4746 100644 --- a/usr.sbin/ntp/ntpq/Makefile +++ b/usr.sbin/ntp/ntpq/Makefile @@ -14,11 +14,7 @@ SRCS= ntpq.c ntpq-opts.c ntpq-subs.c version.c CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \ -I${.CURDIR}/../../../contrib/ntp/libopts -DPADD= ${LIBNTP} ${LIBM} ${LIBMD} ${LIBOPTS} -LDADD= ${LIBNTP} -lm -lmd ${LIBOPTS} - -DPADD+= ${LIBEDIT} ${LIBTERMCAPW} -LDADD+= -ledit -ltermcapw +LIBADD+= edit md ntp opts CFLAGS+= -DHAVE_LIBEDIT -DHAVE_READLINE_READLINE_H \ -I${DESTDIR}/${INCLUDEDIR}/edit diff --git a/usr.sbin/ntp/ntptime/Makefile b/usr.sbin/ntp/ntptime/Makefile index d3bf7a74cfd9..65f1a714da92 100644 --- a/usr.sbin/ntp/ntptime/Makefile +++ b/usr.sbin/ntp/ntptime/Makefile @@ -7,7 +7,6 @@ MAN= CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ -DPADD= ${LIBNTP} -LDADD= ${LIBNTP} +LIBADD= ntp .include diff --git a/usr.sbin/ntp/sntp/Makefile b/usr.sbin/ntp/sntp/Makefile index 11316c514296..a2eede119aa8 100644 --- a/usr.sbin/ntp/sntp/Makefile +++ b/usr.sbin/ntp/sntp/Makefile @@ -10,7 +10,6 @@ CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \ -DPACKAGE=\"sntp\" -DVERSION=\"1.6\" \ -I${.CURDIR}/../../../contrib/ntp/libopts -DPADD= ${LIBM} ${LIBOPTS} -LDADD= -lm ${LIBOPTS} +LIBADD= m opts .include diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile index c372a3c492af..0884b6b528cd 100644 --- a/usr.sbin/pkg/Makefile +++ b/usr.sbin/pkg/Makefile @@ -6,9 +6,6 @@ MAN= pkg.7 CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include .PATH: ${.CURDIR}/../../contrib/libucl/include -DPADD= ${LIBARCHIVE} ${LIBFETCH} ${LIBUCL} ${LIBSBUF} ${LIBSSL} \ - ${LIBCRYPTO} ${LIBM} -LDADD= -larchive -lfetch ${LDUCL} -lsbuf -lssl -lcrypto -lm -USEPRIVATELIB= ucl +LIBADD= archive fetch ucl sbuf crypto .include diff --git a/usr.sbin/pmccontrol/Makefile b/usr.sbin/pmccontrol/Makefile index 0f6dc768d8eb..1940b1ffe123 100644 --- a/usr.sbin/pmccontrol/Makefile +++ b/usr.sbin/pmccontrol/Makefile @@ -5,8 +5,7 @@ PROG= pmccontrol MAN= pmccontrol.8 -DPADD= ${LIBPMC} -LDADD= -lpmc +LIBADD+= pmc SRCS= pmccontrol.c diff --git a/usr.sbin/pmcstat/Makefile b/usr.sbin/pmcstat/Makefile index 78cde444948e..dc5a30a40003 100644 --- a/usr.sbin/pmcstat/Makefile +++ b/usr.sbin/pmcstat/Makefile @@ -5,8 +5,7 @@ PROG= pmcstat MAN= pmcstat.8 -DPADD= ${LIBELF} ${LIBKVM} ${LIBPMC} ${LIBM} ${LIBNCURSESW} -LDADD= -lelf -lkvm -lpmc -lm -lncursesw +LIBADD= elf kvm pmc m ncursesw SRCS= pmcstat.c pmcstat.h pmcstat_log.c \ pmcpl_callgraph.c pmcpl_gprof.c pmcpl_annotate.c \ diff --git a/usr.sbin/powerd/Makefile b/usr.sbin/powerd/Makefile index 62f8da1ba1a4..4434dcf69318 100644 --- a/usr.sbin/powerd/Makefile +++ b/usr.sbin/powerd/Makefile @@ -3,7 +3,6 @@ PROG= powerd MAN= powerd.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/ppp/Makefile b/usr.sbin/ppp/Makefile index 7783f42909b3..e0772af2e53e 100644 --- a/usr.sbin/ppp/Makefile +++ b/usr.sbin/ppp/Makefile @@ -44,8 +44,7 @@ BINOWN= root BINGRP= network M4FLAGS= -LDADD= -lcrypt -lmd -lutil -lz -DPADD= ${LIBCRYPT} ${LIBMD} ${LIBUTIL} ${LIBZ} +LIBADD= md util z .if defined(PPP_CONFDIR) && !empty(PPP_CONFDIR) CFLAGS+=-DPPP_CONFDIR=\"${PPP_CONFDIR}\" @@ -63,8 +62,7 @@ CFLAGS+=-DNOINET6 CFLAGS+=-DNONAT .else SRCS+= nat_cmd.c -LDADD+= -lalias -DPADD+= ${LIBALIAS} +LIBADD+= alias .endif .if defined(PPP_NO_ATM) @@ -83,24 +81,21 @@ SRCS+= id.c CFLAGS+=-DNODES .else SRCS+= chap_ms.c mppe.c -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} +LIBADD+= crypto .endif .if defined(PPP_NO_RADIUS) CFLAGS+=-DNORADIUS .else SRCS+= radius.c -LDADD+= -lradius -DPADD+= ${LIBRADIUS} +LIBADD+= radius .endif .if defined(PPP_NO_NETGRAPH) CFLAGS+=-DNONETGRAPH .else SRCS+= ether.c -LDADD+= -lnetgraph -DPADD+= ${LIBNETGRAPH} +LIBADD+= netgraph .if defined(EXPERIMENTAL_NETGRAPH) CFLAGS+=-DEXPERIMENTAL_NETGRAPH SRCS+= netgraph.c @@ -110,8 +105,7 @@ SRCS+= netgraph.c .if defined(PPP_NO_PAM) CFLAGS+=-DNOPAM .else -LDADD+= ${MINUSLPAM} -DPADD+= ${LIBPAM} +LIBADD+= pam .endif .include diff --git a/usr.sbin/pppctl/Makefile b/usr.sbin/pppctl/Makefile index 4a03b86ad48a..dcb793139bed 100644 --- a/usr.sbin/pppctl/Makefile +++ b/usr.sbin/pppctl/Makefile @@ -5,7 +5,6 @@ MAN= pppctl.8 WARNS?= 2 -DPADD= ${LIBPTHREAD} ${LIBEDIT} ${LIBTERMCAPW} -LDADD= -lpthread -ledit -ltermcapw +LIBADD= edit pthread .include diff --git a/usr.sbin/praliases/Makefile b/usr.sbin/praliases/Makefile index 120028d6997b..6fadc1b61069 100644 --- a/usr.sbin/praliases/Makefile +++ b/usr.sbin/praliases/Makefile @@ -13,17 +13,7 @@ CFLAGS+= -DNEWDB -DNOT_SENDMAIL WARNS?= 2 -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMDBDIR= ${.OBJDIR}/../../lib/libsmdb -LIBSMDB= ${LIBSMDBDIR}/libsmdb.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} -LDADD= ${LIBSMDB} ${LIBSMUTIL} ${LIBSM} +LIBADD= sm smdb smutil SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/usr.sbin/praudit/Makefile b/usr.sbin/praudit/Makefile index 6a61fd131e37..6d85fb342ec6 100644 --- a/usr.sbin/praudit/Makefile +++ b/usr.sbin/praudit/Makefile @@ -10,7 +10,6 @@ MAN= praudit.1 WARNS?= 3 -DPADD= ${LIBBSM} -LDADD= -lbsm +LIBADD= bsm .include diff --git a/usr.sbin/pstat/Makefile b/usr.sbin/pstat/Makefile index 414708cee055..e3b053308282 100644 --- a/usr.sbin/pstat/Makefile +++ b/usr.sbin/pstat/Makefile @@ -6,7 +6,6 @@ LINKS= ${BINDIR}/pstat ${BINDIR}/swapinfo MAN= pstat.8 MLINKS= pstat.8 swapinfo.8 -DPADD= ${LIBKVM} ${LIBUTIL} -LDADD= -lkvm -lutil +LIBADD= kvm util .include diff --git a/usr.sbin/pw/Makefile b/usr.sbin/pw/Makefile index 8c5acf901d1c..269b145ece15 100644 --- a/usr.sbin/pw/Makefile +++ b/usr.sbin/pw/Makefile @@ -8,8 +8,7 @@ SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \ WARNS?= 2 -DPADD= ${LIBCRYPT} ${LIBUTIL} -LDADD= -lcrypt -lutil +LIBADD= crypt util .include diff --git a/usr.sbin/quotaon/Makefile b/usr.sbin/quotaon/Makefile index 23ba8d1dc4c8..ec3dc1ab7e15 100644 --- a/usr.sbin/quotaon/Makefile +++ b/usr.sbin/quotaon/Makefile @@ -6,7 +6,6 @@ LINKS= ${BINDIR}/quotaon ${BINDIR}/quotaoff MAN= quotaon.8 MLINKS= quotaon.8 quotaoff.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/rarpd/Makefile b/usr.sbin/rarpd/Makefile index 52a9f92d7688..b7816cddedd3 100644 --- a/usr.sbin/rarpd/Makefile +++ b/usr.sbin/rarpd/Makefile @@ -4,8 +4,7 @@ PROG= rarpd MAN= rarpd.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 3 # This breaks with format strings returned by expand_syslog_m().. argh! diff --git a/usr.sbin/repquota/Makefile b/usr.sbin/repquota/Makefile index ed8013285597..78fd39832cf8 100644 --- a/usr.sbin/repquota/Makefile +++ b/usr.sbin/repquota/Makefile @@ -3,7 +3,6 @@ PROG= repquota MAN= repquota.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/rpc.lockd/Makefile b/usr.sbin/rpc.lockd/Makefile index 139f4bc661c8..16b4d4f8a5c1 100644 --- a/usr.sbin/rpc.lockd/Makefile +++ b/usr.sbin/rpc.lockd/Makefile @@ -9,8 +9,7 @@ SRCS= kern.c nlm_prot_svc.c lockd.c lock_proc.c lockd_lock.c CFLAGS+= -I. -I${DESTDIR}/usr/include/rpcsvc WARNS?= 3 -DPADD= ${LIBRPCSVC} ${LIBUTIL} -LDADD= -lrpcsvc -lutil +LIBADD= rpcsvc util CLEANFILES= nlm_prot_svc.c nlm_prot.h test diff --git a/usr.sbin/rpc.statd/Makefile b/usr.sbin/rpc.statd/Makefile index 6fa2b1ed10da..43504e4561b6 100644 --- a/usr.sbin/rpc.statd/Makefile +++ b/usr.sbin/rpc.statd/Makefile @@ -7,8 +7,7 @@ SRCS= file.c sm_inter_svc.c sm_inter.h statd.c procs.c CFLAGS+= -I. WARNS?= 2 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc CLEANFILES= sm_inter_svc.c sm_inter.h diff --git a/usr.sbin/rpc.yppasswdd/Makefile b/usr.sbin/rpc.yppasswdd/Makefile index a9d3a75b333d..5f5fb773c065 100644 --- a/usr.sbin/rpc.yppasswdd/Makefile +++ b/usr.sbin/rpc.yppasswdd/Makefile @@ -20,8 +20,7 @@ CFLAGS+= -I${.CURDIR}/../../usr.sbin/vipw \ -I${.CURDIR}/../../usr.sbin/ypserv \ -I${.CURDIR}/../../libexec/ypxfr \ -I${.CURDIR} -I. -DPADD= ${LIBRPCSVC} ${LIBCRYPT} ${LIBUTIL} -LDADD= -lrpcsvc -lcrypt -lutil +LIBADD= rpcsvc crypt util CLEANFILES= ${GENSRCS} diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile index 03c1142f5efa..d5c346e2c3e2 100644 --- a/usr.sbin/rpc.ypupdated/Makefile +++ b/usr.sbin/rpc.ypupdated/Makefile @@ -13,8 +13,7 @@ CFLAGS+= -I${.CURDIR}/../ypserv -I. -I${.CURDIR}/../../libexec/ypxfr WARNS?= 1 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc CLEANFILES= ypupdate_prot_svc.c ypupdate_prot.h diff --git a/usr.sbin/rpc.ypxfrd/Makefile b/usr.sbin/rpc.ypxfrd/Makefile index 05971b16bfd1..903ac164bbf1 100644 --- a/usr.sbin/rpc.ypxfrd/Makefile +++ b/usr.sbin/rpc.ypxfrd/Makefile @@ -11,8 +11,7 @@ CFLAGS+= -I. -DXFRBLOCKSIZE=65535 WARNS?= 2 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc CLEANFILES= ypxfrd_svc.c ypxfrd.h diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile index 44a030eea375..2b679f416277 100644 --- a/usr.sbin/rpcbind/Makefile +++ b/usr.sbin/rpcbind/Makefile @@ -16,7 +16,6 @@ CFLAGS+= -DINET6 WARNS?= 1 -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap .include diff --git a/usr.sbin/rrenumd/Makefile b/usr.sbin/rrenumd/Makefile index 091e52878c3a..8c82fc31aa4a 100644 --- a/usr.sbin/rrenumd/Makefile +++ b/usr.sbin/rrenumd/Makefile @@ -23,8 +23,7 @@ YFLAGS= -d WARNS?= 2 -LDADD= -lipsec -ll -ly -DPADD= ${LIBIPSEC} ${LIBL} ${LIBY} +LIBADD= ipsec l y CLEANFILES= y.tab.h SRCS+= y.tab.h diff --git a/usr.sbin/rtadvd/Makefile b/usr.sbin/rtadvd/Makefile index d48832d021cf..33e90b64c422 100644 --- a/usr.sbin/rtadvd/Makefile +++ b/usr.sbin/rtadvd/Makefile @@ -19,8 +19,7 @@ MAN= rtadvd.conf.5 rtadvd.8 SRCS= rtadvd.c rrenum.c advcap.c if.c config.c timer.c timer_subr.c \ control.c control_server.c -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util CFLAGS+= -DHAVE_ARC4RANDOM diff --git a/usr.sbin/rtsold/Makefile b/usr.sbin/rtsold/Makefile index efc322c673be..53dea0397303 100644 --- a/usr.sbin/rtsold/Makefile +++ b/usr.sbin/rtsold/Makefile @@ -21,7 +21,6 @@ SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c WARNS?= 3 CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DPADD= ${LIBKVM} -LDADD= -lkvm +LIBADD= kvm .include diff --git a/usr.sbin/sendmail/Makefile b/usr.sbin/sendmail/Makefile index 893b6fd0d70a..1537d33ff1ef 100644 --- a/usr.sbin/sendmail/Makefile +++ b/usr.sbin/sendmail/Makefile @@ -45,17 +45,7 @@ CFLAGS+= -DNETINET6 WARNS?= 1 -DPADD= ${LIBUTIL} ${LIBWRAP} -LDADD= -lutil -lwrap - -LIBSMDIR= ${.OBJDIR}/../../lib/libsm -LIBSM= ${LIBSMDIR}/libsm.a - -LIBSMUTILDIR= ${.OBJDIR}/../../lib/libsmutil -LIBSMUTIL= ${LIBSMUTILDIR}/libsmutil.a - -DPADD+= ${LIBSMUTIL} ${LIBSM} -LDADD+= ${LIBSMUTIL} ${LIBSM} +LIBADD= util wrap sm smutil SRCS+= sm_os.h CLEANFILES+=sm_os.h @@ -63,8 +53,7 @@ CLEANFILES+=sm_os.h .if ${MK_OPENSSL} != "no" # STARTTLS support CFLAGS+= -DSTARTTLS -D_FFR_TLS_1 -DPADD+= ${LIBSSL} ${LIBCRYPTO} -LDADD+= -lssl -lcrypto +LIBADD+= ssl crypto .endif # User customizations to the sendmail build environment diff --git a/usr.sbin/services_mkdb/Makefile b/usr.sbin/services_mkdb/Makefile index e61c6dfa7d16..05a4b76bc271 100644 --- a/usr.sbin/services_mkdb/Makefile +++ b/usr.sbin/services_mkdb/Makefile @@ -4,7 +4,6 @@ PROG= services_mkdb MAN= services_mkdb.8 SRCS= services_mkdb.c uniq.c extern.h -DPADD+= ${LIBUTIL} -LDADD+= -lutil +LIBADD= util .include diff --git a/usr.sbin/snapinfo/Makefile b/usr.sbin/snapinfo/Makefile index c5175f15befc..76013744e988 100644 --- a/usr.sbin/snapinfo/Makefile +++ b/usr.sbin/snapinfo/Makefile @@ -4,7 +4,6 @@ PROG= snapinfo MAN= snapinfo.8 -DPADD= ${LIBUFS} -LDADD= -lufs +LIBADD= ufs -.include +.include diff --git a/usr.sbin/spray/Makefile b/usr.sbin/spray/Makefile index c2515e0c117e..f0070726c820 100644 --- a/usr.sbin/spray/Makefile +++ b/usr.sbin/spray/Makefile @@ -3,7 +3,6 @@ PROG= spray MAN= spray.8 -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc +LIBADD= rpcsvc .include diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile index 069e093ccd21..716efbe7d597 100644 --- a/usr.sbin/syslogd/Makefile +++ b/usr.sbin/syslogd/Makefile @@ -9,8 +9,7 @@ PROG= syslogd MAN= syslog.conf.5 syslogd.8 SRCS= syslogd.c ttymsg.c -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 3 diff --git a/usr.sbin/tcpdchk/Makefile b/usr.sbin/tcpdchk/Makefile index e9799165c61f..5faea18a3af4 100644 --- a/usr.sbin/tcpdchk/Makefile +++ b/usr.sbin/tcpdchk/Makefile @@ -17,7 +17,6 @@ CFLAGS+=-DINET6 WARNS?= 0 -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap .include diff --git a/usr.sbin/tcpdmatch/Makefile b/usr.sbin/tcpdmatch/Makefile index f8ccf8adc7da..bbe29a458627 100644 --- a/usr.sbin/tcpdmatch/Makefile +++ b/usr.sbin/tcpdmatch/Makefile @@ -16,7 +16,6 @@ CFLAGS+=-DINET6 WARNS?= 0 -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap .include diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile index fcaa13e3a354..9e6a42435d7c 100644 --- a/usr.sbin/tcpdump/tcpdump/Makefile +++ b/usr.sbin/tcpdump/tcpdump/Makefile @@ -160,16 +160,13 @@ CFLAGS+= -DINET6 CFLAGS+= -DLBL_ALIGN .endif -DPADD= ${LIBL} ${LIBPCAP} -LDADD= -ll -lpcap +LIBADD= l pcap .if ${MK_CASPER} != "no" -DPADD+= ${LIBCAPSICUM} ${LIBNV} -LDADD+= -lcapsicum -lnv +LIBADD+= capsicum CFLAGS+=-DHAVE_LIBCAPSICUM .endif .if ${MK_OPENSSL} != "no" -DPADD+= ${LIBCRYPTO} -LDADD+= -lcrypto +LIBADD+= crypto CFLAGS+= -I${DESTDIR}/usr/include/openssl CFLAGS+= -DHAVE_LIBCRYPTO -DHAVE_OPENSSL_EVP_H .endif diff --git a/usr.sbin/timed/timed/Makefile b/usr.sbin/timed/timed/Makefile index af70b066b7ca..d4ce0fbca864 100644 --- a/usr.sbin/timed/timed/Makefile +++ b/usr.sbin/timed/timed/Makefile @@ -8,8 +8,7 @@ MAN= timed.8 SRCS= acksend.c candidate.c correct.c master.c networkdelta.c readmsg.c \ slave.c timed.c byteorder.c measure.c cksum.c -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util WARNS?= 1 diff --git a/usr.sbin/traceroute/Makefile b/usr.sbin/traceroute/Makefile index 12f9a0b7cddf..a3b6a14afdfc 100644 --- a/usr.sbin/traceroute/Makefile +++ b/usr.sbin/traceroute/Makefile @@ -25,8 +25,7 @@ CFLAGS+= -DIPSEC # CFLAGS+= -DSANE_PRECISION .if !defined(TRACEROUTE_NO_IPSEC) -DPADD= ${LIBIPSEC} -LDADD= -lipsec +LIBADD+= ipsec .endif CFLAGS+= -I${TRACEROUTE_DISTDIR} diff --git a/usr.sbin/traceroute6/Makefile b/usr.sbin/traceroute6/Makefile index 4428d5b46389..fc0b5fe63c89 100644 --- a/usr.sbin/traceroute6/Makefile +++ b/usr.sbin/traceroute6/Makefile @@ -27,7 +27,6 @@ CFLAGS+= -I${.CURDIR} -I${TRACEROUTE_DISTDIR} -I. WARNS?= 3 -DPADD= ${LIBIPSEC} -LDADD= -lipsec +LIBADD= ipsec .include diff --git a/usr.sbin/tzsetup/Makefile b/usr.sbin/tzsetup/Makefile index 4ef65331cc15..de7375f0002e 100644 --- a/usr.sbin/tzsetup/Makefile +++ b/usr.sbin/tzsetup/Makefile @@ -7,7 +7,6 @@ CFLAGS+= -I${.CURDIR}/../../contrib/dialog -I. WARNS?= 3 -DPADD= ${LIBDIALOG} ${LIBNCURSESW} ${LIBM} -LDADD= -ldialog -lncursesw -lm +LIBADD= dialog ncursesw .include diff --git a/usr.sbin/ugidfw/Makefile b/usr.sbin/ugidfw/Makefile index d89bc857f5bf..7a5453e49d68 100644 --- a/usr.sbin/ugidfw/Makefile +++ b/usr.sbin/ugidfw/Makefile @@ -3,7 +3,6 @@ PROG= ugidfw MAN= ugidfw.8 -DPADD= ${LIBUGIDFW} -LDADD= -lugidfw +LIBADD= ugidfw .include diff --git a/usr.sbin/uhsoctl/Makefile b/usr.sbin/uhsoctl/Makefile index 565b2e657813..264384b755c1 100644 --- a/usr.sbin/uhsoctl/Makefile +++ b/usr.sbin/uhsoctl/Makefile @@ -4,7 +4,6 @@ PROG= uhsoctl MAN= uhsoctl.1 WARNS?= 1 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/unbound/anchor/Makefile b/usr.sbin/unbound/anchor/Makefile index 970fb705e183..64e01d2ef836 100644 --- a/usr.sbin/unbound/anchor/Makefile +++ b/usr.sbin/unbound/anchor/Makefile @@ -10,9 +10,7 @@ EXPATDIR= ${.CURDIR}/../../../contrib/expat PROG= unbound-anchor SRCS= unbound-anchor.c CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -I${EXPATDIR}/lib -DPADD= ${LIBUNBOUND} ${LIBLDNS} ${LIBUTIL} ${LIBBSDXML} ${LIBSSL} ${LIBCRYPTO} ${LIBPTHREAD} -LDADD= ${LDUNBOUND} ${LDLDNS} -lutil -lbsdxml -lssl -lcrypto -lpthread -USEPRIVATELIB= ldns +LIBADD= unbound bsdxml ssl crypto pthread MAN= unbound-anchor.8 .include diff --git a/usr.sbin/unbound/checkconf/Makefile b/usr.sbin/unbound/checkconf/Makefile index 0993d3d5745c..884465ba70a0 100644 --- a/usr.sbin/unbound/checkconf/Makefile +++ b/usr.sbin/unbound/checkconf/Makefile @@ -9,9 +9,7 @@ UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound PROG= unbound-checkconf SRCS= unbound-checkconf.c worker_cb.c CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -DPADD= ${LIBUNBOUND} ${LIBLDNS} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBPTHREAD} -LDADD= ${LDUNBOUND} ${LDLDNS} -lutil -lssl -lcrypto -lpthread -USEPRIVATELIB= ldns +LIBADD= unbound pthread MAN= unbound-checkconf.8 .include diff --git a/usr.sbin/unbound/control/Makefile b/usr.sbin/unbound/control/Makefile index 2989e739ed25..16141277bae3 100644 --- a/usr.sbin/unbound/control/Makefile +++ b/usr.sbin/unbound/control/Makefile @@ -10,9 +10,7 @@ PROG= unbound-control SCRIPTS= unbound-control-setup.sh SRCS= unbound-control.c worker_cb.c CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -DPADD= ${LIBUNBOUND} ${LIBLDNS} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBPTHREAD} -LDADD= ${LDUNBOUND} ${LDLDNS} -lutil -lssl -lcrypto -lpthread -USEPRIVATELIB= ldns +LIBADD= unbound crypto ssl pthread MAN= unbound-control.8 .include diff --git a/usr.sbin/unbound/daemon/Makefile b/usr.sbin/unbound/daemon/Makefile index a8b1bb263865..f90e06ee17cd 100644 --- a/usr.sbin/unbound/daemon/Makefile +++ b/usr.sbin/unbound/daemon/Makefile @@ -9,9 +9,7 @@ UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound PROG= unbound SRCS= acl_list.c cachedump.c daemon.c remote.c stats.c unbound.c worker.c CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -DPADD= ${LIBUNBOUND} ${LIBLDNS} ${LIBUTIL} ${LIBSSL} ${LIBCRYPTO} ${LIBPTHREAD} -LDADD= ${LDUNBOUND} ${LDLDNS} -lutil -lssl -lcrypto -lpthread -USEPRIVATELIB= ldns +LIBADD= unbound util ssl crypto pthread MAN= unbound.8 unbound.conf.5 .include diff --git a/usr.sbin/usbconfig/Makefile b/usr.sbin/usbconfig/Makefile index 0aa51fae17f8..bfc4b6354d2a 100644 --- a/usr.sbin/usbconfig/Makefile +++ b/usr.sbin/usbconfig/Makefile @@ -4,7 +4,6 @@ PROG= usbconfig MAN= usbconfig.8 SRCS= usbconfig.c dump.c -DPADD+= ${LIBUSB} -LDADD+= -lusb +LIBADD= usb .include diff --git a/usr.sbin/vipw/Makefile b/usr.sbin/vipw/Makefile index d98e4019adea..f36825de6df9 100644 --- a/usr.sbin/vipw/Makefile +++ b/usr.sbin/vipw/Makefile @@ -4,7 +4,6 @@ PROG= vipw MAN= vipw.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +LIBADD= util .include diff --git a/usr.sbin/watch/Makefile b/usr.sbin/watch/Makefile index 184d33187157..981aec0a4749 100644 --- a/usr.sbin/watch/Makefile +++ b/usr.sbin/watch/Makefile @@ -5,7 +5,6 @@ MAN= watch.8 WARNS?= 2 -DPADD= ${LIBTERMCAPW} -LDADD= -ltermcapw +LIBADD= ncursesw .include diff --git a/usr.sbin/watchdogd/Makefile b/usr.sbin/watchdogd/Makefile index 5df7946cb1f7..bce983f6a92c 100644 --- a/usr.sbin/watchdogd/Makefile +++ b/usr.sbin/watchdogd/Makefile @@ -4,8 +4,7 @@ PROG= watchdogd LINKS= ${BINDIR}/watchdogd ${BINDIR}/watchdog MAN= watchdogd.8 watchdog.8 -LDADD= -lutil -DPADD= ${LIBUTIL} +LIBADD= util .include diff --git a/usr.sbin/wpa/Makefile.crypto b/usr.sbin/wpa/Makefile.crypto index 94367bbfc949..3049011a433a 100644 --- a/usr.sbin/wpa/Makefile.crypto +++ b/usr.sbin/wpa/Makefile.crypto @@ -2,8 +2,7 @@ .if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH) SRCS+= crypto_openssl.c random.c sha1-prf.c sha256-prf.c -DPADD+= ${LIBSSL} ${LIBCRYPTO} -LDADD+= -lssl -lcrypto +LIBADD+= ssl crypto CFLAGS+= -DCONFIG_SHA256 .else CFLAGS+=-DCONFIG_CRYPTO_INTERNAL diff --git a/usr.sbin/wpa/hostapd/Makefile b/usr.sbin/wpa/hostapd/Makefile index 7ab542f11386..4621ad37e6d6 100644 --- a/usr.sbin/wpa/hostapd/Makefile +++ b/usr.sbin/wpa/hostapd/Makefile @@ -46,8 +46,7 @@ CFLAGS+=-DCONFIG_DRIVER_BSD \ CFLAGS+= -DCONFIG_IPV6 .endif #CFLAGS+= -g -DPADD+= ${LIBPCAP} ${LIBUTIL} -LDADD+= -lpcap -lutil +LIBADD+= pcap util # User customizations for wpa_supplicant/hostapd build environment CFLAGS+=${HOSTAPD_CFLAGS} diff --git a/usr.sbin/wpa/hostapd_cli/Makefile b/usr.sbin/wpa/hostapd_cli/Makefile index 3542aacfdfdd..48af1401a8d2 100644 --- a/usr.sbin/wpa/hostapd_cli/Makefile +++ b/usr.sbin/wpa/hostapd_cli/Makefile @@ -10,8 +10,7 @@ SRCS= common.c edit.c eloop.c hostapd_cli.c os_unix.c wpa_ctrl.c wpa_debug.c CFLAGS+= -DCONFIG_CTRL_IFACE CFLAGS+= -DCONFIG_CTRL_IFACE_UNIX -DPADD+= ${LIBUTIL} -LDADD+= -lutil +LIBADD+= util MAN= hostapd_cli.8 diff --git a/usr.sbin/wpa/wpa_cli/Makefile b/usr.sbin/wpa/wpa_cli/Makefile index 9530b73c4c23..3203829d98af 100644 --- a/usr.sbin/wpa/wpa_cli/Makefile +++ b/usr.sbin/wpa/wpa_cli/Makefile @@ -15,7 +15,6 @@ CFLAGS+= -DCONFIG_CTRL_IFACE_UNIX CFLAGS+= -D_DIRENT_HAVE_D_TYPE CFLAGS+= -DCONFIG_WPA_CLI_EDIT=y -LDADD+= -lutil -DPADD+= ${LIBUTIL} +LIBADD+= util .include diff --git a/usr.sbin/wpa/wpa_passphrase/Makefile b/usr.sbin/wpa/wpa_passphrase/Makefile index d0f51985ba79..c1384817dddc 100644 --- a/usr.sbin/wpa/wpa_passphrase/Makefile +++ b/usr.sbin/wpa/wpa_passphrase/Makefile @@ -11,8 +11,7 @@ SRCS= common.c md5-internal.c md5.c os_unix.c sha1-internal.c sha1-pbkdf2.c sha1 CFLAGS+= -DINTERNAL_SHA1 CFLAGS+= -DINTERNAL_MD5 -DPADD+= ${LIBUTIL} -LDADD+= -lutil +LIBADD+= util MAN= wpa_passphrase.8 diff --git a/usr.sbin/wpa/wpa_priv/Makefile b/usr.sbin/wpa/wpa_priv/Makefile index 4dbc63155d6a..cf776786f97e 100644 --- a/usr.sbin/wpa/wpa_priv/Makefile +++ b/usr.sbin/wpa/wpa_priv/Makefile @@ -9,8 +9,7 @@ PROG= wpa_priv SRCS= drivers.c os_unix.c eloop.c common.c wpa_debug.c wpabuf.c wpa_priv.c \ driver_common.c l2_packet_freebsd.c -DPADD+= ${LIBPCAP} -LDADD+= -lpcap +LIBADD= pcap .include "${.CURDIR}/../Makefile.crypto" diff --git a/usr.sbin/wpa/wpa_supplicant/Makefile b/usr.sbin/wpa/wpa_supplicant/Makefile index 673a04d27a7c..dd40766f19d0 100644 --- a/usr.sbin/wpa/wpa_supplicant/Makefile +++ b/usr.sbin/wpa/wpa_supplicant/Makefile @@ -49,8 +49,7 @@ CFLAGS+=-DCONFIG_BACKEND_FILE \ -DCONFIG_GAS \ -DPKCS12_FUNCS #CFLAGS+= -g -DPADD+= ${LIBPCAP} ${LIBUTIL} -LDADD+= -lpcap -lutil +LIBADD= pcap util # User customizations to the wpa_supplicant build environment CFLAGS+=${WPA_SUPPLICANT_CFLAGS} @@ -127,8 +126,7 @@ NEED_FIPS186_2_PRF=y # .if !empty(CFLAGS:M*-DPCSC_FUNCS) SRCS+= pcsc_funcs.c -DPADD+=${LIBPTHREAD} -LDADD+=-lpcsclite -lpthread +LIBADD+= pcslite pthread .endif .if !empty(CFLAGS:M*-DEAP_GPSK) diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile index cb24c43e71ee..28d6a66ec27f 100644 --- a/usr.sbin/ypserv/Makefile +++ b/usr.sbin/ypserv/Makefile @@ -12,8 +12,7 @@ CFLAGS+= -DDB_CACHE -DTCP_WRAPPER -I. WARNS?= 0 -DPADD= ${LIBWRAP} -LDADD= -lwrap +LIBADD= wrap CLEANFILES= yp_svc.c ypxfr_clnt.c yp.h