Revert r324358, some cruft when in with it, it will be

properly reimported in another commit
This commit is contained in:
Baptiste Daroussin 2017-10-06 12:30:54 +00:00
parent e836f6f402
commit 8194a60137
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324361
11 changed files with 32 additions and 1070 deletions

View file

@ -1,11 +0,0 @@
PROG= ctfdump
SRCS= ctfdump.c elf.c
CFLAGS+= -W -Wall -Wstrict-prototypes -Wno-unused -Wunused-variable
CFLAGS+= -DZLIB
LDADD+= -lz
DPADD+= ${LIBZ}
.include <bsd.prog.mk>

View file

@ -1,53 +0,0 @@
.\"
.\" Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt CTFDUMP 1
.Os
.Sh NAME
.Nm ctfdump
.Nd display CTF information
.Sh SYNOPSIS
.Nm ctfdump
.Op Fl dfhlst
file ...
.Sh DESCRIPTION
The
.Nm
utility display CTF information from the
.Dv \.SUNW_ctf
section of an
.Xr elf 5
file or from a raw CTF file.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl d
Display the object section.
.It Fl f
Display the function section.
.It Fl h
Dump the CTF header.
.It Fl l
Display the label section.
.It Fl s
Display the string table.
.It Fl t
Display the type section.
.El
.Sh EXIT STATUS
.Ex -std ctfdump
.Sh SEE ALSO
.Xr elf 5

View file

@ -1,638 +0,0 @@
/*
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/elf.h>
#include <sys/mman.h>
#include <sys/ctf.h>
#include <err.h>
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef ZLIB
#include <zlib.h>
#endif /* ZLIB */
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
#ifndef ELF_STRTAB
#define ELF_STRTAB ".strtab"
#endif
#ifndef ELF_CTF
#define ELF_CTF ".SUNW_ctf"
#endif
#define DUMP_OBJECT (1 << 0)
#define DUMP_FUNCTION (1 << 1)
#define DUMP_HEADER (1 << 2)
#define DUMP_LABEL (1 << 3)
#define DUMP_STRTAB (1 << 4)
#define DUMP_STATISTIC (1 << 5)
#define DUMP_TYPE (1 << 6)
int dump(const char *, uint8_t);
int isctf(const char *, size_t);
__dead2 void usage(void);
int ctf_dump(const char *, size_t, uint8_t);
uint32_t ctf_dump_type(struct ctf_header *, const char *, off_t,
uint32_t, uint32_t);
const char *ctf_kind2name(uint16_t);
const char *ctf_enc2name(uint16_t);
const char *ctf_off2name(struct ctf_header *, const char *, off_t,
uint32_t);
int elf_dump(char *, size_t, uint8_t);
const char *elf_idx2sym(size_t *, uint8_t);
/* elf.c */
int iself(const char *, size_t);
int elf_getshstab(const char *, size_t, const char **, size_t *);
ssize_t elf_getsymtab(const char *, const char *, size_t,
const Elf_Sym **, size_t *);
ssize_t elf_getsection(char *, const char *, const char *,
size_t, const char **, size_t *);
char *decompress(const char *, size_t, size_t);
int
main(int argc, char *argv[])
{
const char *filename;
uint8_t flags = 0;
int ch, error = 0;
setlocale(LC_ALL, "");
while ((ch = getopt(argc, argv, "dfhlst")) != -1) {
switch (ch) {
case 'd':
flags |= DUMP_OBJECT;
break;
case 'f':
flags |= DUMP_FUNCTION;
break;
case 'h':
flags |= DUMP_HEADER;
break;
case 'l':
flags |= DUMP_LABEL;
break;
case 's':
flags |= DUMP_STRTAB;
break;
case 't':
flags |= DUMP_TYPE;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc <= 0)
usage();
/* Dump everything by default */
if (flags == 0)
flags = 0xff;
while ((filename = *argv++) != NULL)
error |= dump(filename, flags);
return error;
}
int
dump(const char *path, uint8_t flags)
{
struct stat st;
int fd, error = 1;
char *p;
fd = open(path, O_RDONLY);
if (fd == -1) {
warn("open");
return 1;
}
if (fstat(fd, &st) == -1) {
warn("fstat");
return 1;
}
if ((uintmax_t)st.st_size > SIZE_MAX) {
warnx("file too big to fit memory");
return 1;
}
p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (p == MAP_FAILED)
err(1, "mmap");
if (iself(p, st.st_size)) {
error = elf_dump(p, st.st_size, flags);
} else if (isctf(p, st.st_size)) {
error = ctf_dump(p, st.st_size, flags);
}
munmap(p, st.st_size);
close(fd);
return error;
}
const char *strtab;
const Elf_Sym *symtab;
size_t strtabsz, nsymb;
const char *
elf_idx2sym(size_t *idx, uint8_t type)
{
const Elf_Sym *st;
size_t i;
for (i = *idx + 1; i < nsymb; i++) {
st = &symtab[i];
if (ELF_ST_TYPE(st->st_info) != type)
continue;
*idx = i;
return strtab + st->st_name;
}
return NULL;
}
int
elf_dump(char *p, size_t filesize, uint8_t flags)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
const char *shstab;
size_t i, shstabsz;
/* Find section header string table location and size. */
if (elf_getshstab(p, filesize, &shstab, &shstabsz))
return 1;
/* Find symbol table location and number of symbols. */
if (elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb) == -1)
warnx("symbol table not found");
/* Find string table location and size. */
if (elf_getsection(p, ELF_STRTAB, shstab, shstabsz, &strtab,
&strtabsz) == -1)
warnx("string table not found");
/* Find CTF section and dump it. */
for (i = 0; i < eh->e_shnum; i++) {
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if ((sh->sh_link >= eh->e_shnum) ||
(sh->sh_name >= shstabsz))
continue;
if (strncmp(shstab + sh->sh_name, ELF_CTF, strlen(ELF_CTF)))
continue;
if (!isctf(p + sh->sh_offset, sh->sh_size))
break;
return ctf_dump(p + sh->sh_offset, sh->sh_size, flags);
}
warnx("%s section not found", ELF_CTF);
return 1;
}
int
isctf(const char *p, size_t filesize)
{
struct ctf_header *cth = (struct ctf_header *)p;
size_t dlen;
if (filesize < sizeof(struct ctf_header)) {
warnx("file too small to be CTF");
return 0;
}
if (cth->cth_magic != CTF_MAGIC || cth->cth_version != CTF_VERSION)
return 0;
dlen = cth->cth_stroff + cth->cth_strlen;
if (dlen > filesize && !(cth->cth_flags & CTF_F_COMPRESS)) {
warnx("bogus file size");
return 0;
}
if ((cth->cth_lbloff & 3) || (cth->cth_objtoff & 1) ||
(cth->cth_funcoff & 1) || (cth->cth_typeoff & 3)) {
warnx("wrongly aligned offset");
return 0;
}
if ((cth->cth_lbloff >= dlen) || (cth->cth_objtoff >= dlen) ||
(cth->cth_funcoff >= dlen) || (cth->cth_typeoff >= dlen)) {
warnx("truncated file");
return 0;
}
if ((cth->cth_lbloff > cth->cth_objtoff) ||
(cth->cth_objtoff > cth->cth_funcoff) ||
(cth->cth_funcoff > cth->cth_typeoff) ||
(cth->cth_typeoff > cth->cth_stroff)) {
warnx("corrupted file");
return 0;
}
return 1;
}
int
ctf_dump(const char *p, size_t size, uint8_t flags)
{
struct ctf_header *cth = (struct ctf_header *)p;
off_t dlen = cth->cth_stroff + cth->cth_strlen;
char *data;
if (cth->cth_flags & CTF_F_COMPRESS) {
data = decompress(p + sizeof(*cth), size - sizeof(*cth), dlen);
if (data == NULL)
return 1;
} else {
data = (char *)p + sizeof(*cth);
}
if (flags & DUMP_HEADER) {
printf(" cth_magic = 0x%04x\n", cth->cth_magic);
printf(" cth_version = %d\n", cth->cth_version);
printf(" cth_flags = 0x%02x\n", cth->cth_flags);
printf(" cth_parlabel = %s\n",
ctf_off2name(cth, data, dlen, cth->cth_parname));
printf(" cth_parname = %s\n",
ctf_off2name(cth, data, dlen, cth->cth_parname));
printf(" cth_lbloff = %d\n", cth->cth_lbloff);
printf(" cth_objtoff = %d\n", cth->cth_objtoff);
printf(" cth_funcoff = %d\n", cth->cth_funcoff);
printf(" cth_typeoff = %d\n", cth->cth_typeoff);
printf(" cth_stroff = %d\n", cth->cth_stroff);
printf(" cth_strlen = %d\n", cth->cth_strlen);
printf("\n");
}
if (flags & DUMP_LABEL) {
uint32_t lbloff = cth->cth_lbloff;
struct ctf_lblent *ctl;
while (lbloff < cth->cth_objtoff) {
ctl = (struct ctf_lblent *)(data + lbloff);
printf(" %5u %s\n", ctl->ctl_typeidx,
ctf_off2name(cth, data, dlen, ctl->ctl_label));
lbloff += sizeof(*ctl);
}
printf("\n");
}
if (flags & DUMP_OBJECT) {
uint32_t objtoff = cth->cth_objtoff;
size_t idx = 0, i = 0;
uint16_t *dsp;
const char *s;
int l;
while (objtoff < cth->cth_funcoff) {
dsp = (uint16_t *)(data + objtoff);
l = printf(" [%zu] %u", i++, *dsp);
if ((s = elf_idx2sym(&idx, STT_OBJECT)) != NULL)
printf("%*s %s (%zu)\n", (14 - l), "", s, idx);
else
printf("\n");
objtoff += sizeof(*dsp);
}
printf("\n");
}
if (flags & DUMP_FUNCTION) {
uint16_t *fsp, kind, vlen;
size_t idx = 0, i = -1;
const char *s;
int l;
fsp = (uint16_t *)(data + cth->cth_funcoff);
while (fsp < (uint16_t *)(data + cth->cth_typeoff)) {
kind = CTF_INFO_KIND(*fsp);
vlen = CTF_INFO_VLEN(*fsp);
s = elf_idx2sym(&idx, STT_FUNC);
fsp++;
i++;
if (kind == CTF_K_UNKNOWN && vlen == 0)
continue;
l = printf(" [%zu] FUNC ", i);
if (s != NULL)
printf("(%s)", s);
printf(" returns: %u args: (", *fsp++);
while (vlen-- > 0)
printf("%u%s", *fsp++, (vlen > 0) ? ", " : "");
printf(")\n");
}
printf("\n");
}
if (flags & DUMP_TYPE) {
uint32_t idx = 1, offset = cth->cth_typeoff;
while (offset < cth->cth_stroff) {
offset += ctf_dump_type(cth, data, dlen, offset, idx++);
}
printf("\n");
}
if (flags & DUMP_STRTAB) {
uint32_t offset = 0;
const char *str;
while (offset < cth->cth_strlen) {
str = ctf_off2name(cth, data, dlen, offset);
printf(" [%u] ", offset);
if (strcmp(str, "(anon)"))
offset += printf("%s\n", str);
else {
printf("\\0\n");
offset++;
}
}
printf("\n");
}
if (cth->cth_flags & CTF_F_COMPRESS)
free(data);
return 0;
}
uint32_t
ctf_dump_type(struct ctf_header *cth, const char *data, off_t dlen,
uint32_t offset, uint32_t idx)
{
const char *p = data + offset;
const struct ctf_type *ctt = (struct ctf_type *)p;
const struct ctf_array *cta;
uint16_t *argp, i, kind, vlen, root;
uint32_t eob, toff;
uint64_t size;
const char *name, *kname;
kind = CTF_INFO_KIND(ctt->ctt_info);
vlen = CTF_INFO_VLEN(ctt->ctt_info);
root = CTF_INFO_ISROOT(ctt->ctt_info);
name = ctf_off2name(cth, data, dlen, ctt->ctt_name);
if (root)
printf(" <%u> ", idx);
else
printf(" [%u] ", idx);
if ((kname = ctf_kind2name(kind)) != NULL)
printf("%s %s", kname, name);
if (ctt->ctt_size <= CTF_MAX_SIZE) {
size = ctt->ctt_size;
toff = sizeof(struct ctf_stype);
} else {
size = CTF_TYPE_LSIZE(ctt);
toff = sizeof(struct ctf_type);
}
switch (kind) {
case CTF_K_UNKNOWN:
case CTF_K_FORWARD:
break;
case CTF_K_INTEGER:
eob = *((uint32_t *)(p + toff));
toff += sizeof(uint32_t);
printf(" encoding=%s offset=%u bits=%u",
ctf_enc2name(CTF_INT_ENCODING(eob)), CTF_INT_OFFSET(eob),
CTF_INT_BITS(eob));
break;
case CTF_K_FLOAT:
eob = *((uint32_t *)(p + toff));
toff += sizeof(uint32_t);
printf(" encoding=0x%x offset=%u bits=%u",
CTF_FP_ENCODING(eob), CTF_FP_OFFSET(eob), CTF_FP_BITS(eob));
break;
case CTF_K_ARRAY:
cta = (struct ctf_array *)(p + toff);
printf(" content: %u index: %u nelems: %u\n", cta->cta_contents,
cta->cta_index, cta->cta_nelems);
toff += sizeof(struct ctf_array);
break;
case CTF_K_FUNCTION:
argp = (uint16_t *)(p + toff);
printf(" returns: %u args: (%u", ctt->ctt_type, *argp);
for (i = 1; i < vlen; i++) {
argp++;
printf(", %u", *argp);
}
printf(")");
toff += (vlen + (vlen & 1)) * sizeof(uint16_t);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
printf(" (%lu bytes)\n", size);
if (size < CTF_LSTRUCT_THRESH) {
for (i = 0; i < vlen; i++) {
struct ctf_member *ctm;
ctm = (struct ctf_member *)(p + toff);
toff += sizeof(struct ctf_member);
printf("\t%s type=%u off=%u\n",
ctf_off2name(cth, data, dlen,
ctm->ctm_name),
ctm->ctm_type, ctm->ctm_offset);
}
} else {
for (i = 0; i < vlen; i++) {
struct ctf_lmember *ctlm;
ctlm = (struct ctf_lmember *)(p + toff);
toff += sizeof(struct ctf_lmember);
printf("\t%s type=%u off=%zu\n",
ctf_off2name(cth, data, dlen,
ctlm->ctlm_name),
ctlm->ctlm_type, CTF_LMEM_OFFSET(ctlm));
}
}
break;
case CTF_K_ENUM:
printf("\n");
for (i = 0; i < vlen; i++) {
struct ctf_enum *cte;
cte = (struct ctf_enum *)(p + toff);
toff += sizeof(struct ctf_enum);
printf("\t%s = %d\n",
ctf_off2name(cth, data, dlen, cte->cte_name),
cte->cte_value);
}
break;
case CTF_K_POINTER:
case CTF_K_TYPEDEF:
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
printf(" refers to %u", ctt->ctt_type);
break;
default:
errx(1, "incorrect type %u at offset %u", kind, offset);
}
printf("\n");
return toff;
}
const char *
ctf_kind2name(uint16_t kind)
{
static const char *kind_name[] = { NULL, "INTEGER", "FLOAT", "POINTER",
"ARRAY", "FUNCTION", "STRUCT", "UNION", "ENUM", "FORWARD",
"TYPEDEF", "VOLATILE", "CONST", "RESTRICT" };
if (kind >= nitems(kind_name))
return NULL;
return kind_name[kind];
}
const char *
ctf_enc2name(uint16_t enc)
{
static const char *enc_name[] = { "SIGNED", "CHAR", "SIGNED CHAR",
"BOOL", "SIGNED BOOL" };
static char invalid[7];
if (enc == CTF_INT_VARARGS)
return "VARARGS";
if (enc > 0 && enc < nitems(enc_name))
return enc_name[enc - 1];
snprintf(invalid, sizeof(invalid), "0x%x", enc);
return invalid;
}
const char *
ctf_off2name(struct ctf_header *cth, const char *data, off_t dlen,
uint32_t offset)
{
const char *name;
if (CTF_NAME_STID(offset) != CTF_STRTAB_0)
return "external";
if (CTF_NAME_OFFSET(offset) >= cth->cth_strlen)
return "exceeds strlab";
if (cth->cth_stroff + CTF_NAME_OFFSET(offset) >= dlen)
return "invalid";
name = data + cth->cth_stroff + CTF_NAME_OFFSET(offset);
if (*name == '\0')
return "(anon)";
return name;
}
char *
decompress(const char *buf, size_t size, size_t len)
{
#ifdef ZLIB
z_stream stream;
char *data;
int error;
data = malloc(len);
if (data == NULL) {
warn(NULL);
return NULL;
}
memset(&stream, 0, sizeof(stream));
stream.next_in = (void *)buf;
stream.avail_in = size;
stream.next_out = (uint8_t *)data;
stream.avail_out = len;
if ((error = inflateInit(&stream)) != Z_OK) {
warnx("zlib inflateInit failed: %s", zError(error));
goto exit;
}
if ((error = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
warnx("zlib inflate failed: %s", zError(error));
inflateEnd(&stream);
goto exit;
}
if ((error = inflateEnd(&stream)) != Z_OK) {
warnx("zlib inflateEnd failed: %s", zError(error));
goto exit;
}
if (stream.total_out != len) {
warnx("decompression failed: %zu != %zu",
stream.total_out, len);
goto exit;
}
return data;
exit:
free(data);
#endif /* ZLIB */
return NULL;
}
__dead2 void
usage(void)
{
fprintf(stderr, "usage: %s [-dfhlst] file ...\n",
getprogname());
exit(1);
}

View file

@ -1,287 +0,0 @@
/*
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
#include <sys/elf.h>
#include <machine/reloc.h>
#include <assert.h>
#include <err.h>
#include <string.h>
#define ELF_SYMTAB ".symtab"
#define Elf_RelA __CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_Rela)
static int elf_reloc_size(unsigned long);
static void elf_reloc_apply(const char *, const char *, size_t, ssize_t,
char *, size_t);
int
iself(const char *p, size_t filesize)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
if (filesize < (off_t)sizeof(Elf_Ehdr)) {
warnx("file too small to be ELF");
return 0;
}
if (eh->e_ehsize < sizeof(Elf_Ehdr) || !IS_ELF(*eh))
return 0;
if (eh->e_ident[EI_CLASS] != ELF_CLASS) {
warnx("unexpected word size %u", eh->e_ident[EI_CLASS]);
return 0;
}
if (eh->e_ident[EI_VERSION] != ELF_TARG_VER) {
warnx("unexpected version %u", eh->e_ident[EI_VERSION]);
return 0;
}
if (eh->e_ident[EI_DATA] > ELFDATA2MSB) {
warnx("unexpected data format %u", eh->e_ident[EI_DATA]);
return 0;
}
if (eh->e_shoff > filesize) {
warnx("bogus section table offset 0x%lx", (off_t)eh->e_shoff);
return 0;
}
if (eh->e_shentsize < sizeof(Elf_Shdr)) {
warnx("bogus section header size %u", eh->e_shentsize);
return 0;
}
if (eh->e_shnum > (filesize - eh->e_shoff) / eh->e_shentsize) {
warnx("bogus section header count %u", eh->e_shnum);
return 0;
}
if (eh->e_shstrndx >= eh->e_shnum) {
warnx("bogus string table index %u", eh->e_shstrndx);
return 0;
}
return 1;
}
int
elf_getshstab(const char *p, size_t filesize, const char **shstab,
size_t *shstabsize)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
sh = (Elf_Shdr *)(p + eh->e_shoff + eh->e_shstrndx * eh->e_shentsize);
if (sh->sh_type != SHT_STRTAB) {
warnx("unexpected string table type");
return -1;
}
if (sh->sh_offset > filesize) {
warnx("bogus string table offset");
return -1;
}
if (sh->sh_size > filesize - sh->sh_offset) {
warnx("bogus string table size");
return -1;
}
if (shstab != NULL)
*shstab = p + sh->sh_offset;
if (shstabsize != NULL)
*shstabsize = sh->sh_size;
return 0;
}
ssize_t
elf_getsymtab(const char *p, const char *shstab, size_t shstabsz,
const Elf_Sym **symtab, size_t *nsymb)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
size_t snlen;
ssize_t i;
snlen = strlen(ELF_SYMTAB);
for (i = 0; i < eh->e_shnum; i++) {
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if (sh->sh_type != SHT_SYMTAB)
continue;
if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
continue;
if (strncmp(shstab + sh->sh_name, ELF_SYMTAB, snlen) == 0) {
if (symtab != NULL)
*symtab = (Elf_Sym *)(p + sh->sh_offset);
if (nsymb != NULL)
*nsymb = (sh->sh_size / sh->sh_entsize);
return i;
}
}
return -1;
}
ssize_t
elf_getsection(char *p, const char *sname, const char *shstab,
size_t shstabsz, const char **psdata, size_t *pssz)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
char *sdata = NULL;
size_t snlen, ssz = 0;
ssize_t sidx, i;
snlen = strlen(sname);
if (snlen == 0)
return -1;
/* Find the given section. */
for (i = 0; i < eh->e_shnum; i++) {
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
continue;
if (strncmp(shstab + sh->sh_name, sname, snlen) == 0) {
sidx = i;
sdata = p + sh->sh_offset;
ssz = sh->sh_size;
elf_reloc_apply(p, shstab, shstabsz, sidx, sdata, ssz);
break;
}
}
if (sdata == NULL)
return -1;
if (psdata != NULL)
*psdata = sdata;
if (pssz != NULL)
*pssz = ssz;
return sidx;
}
static int
elf_reloc_size(unsigned long type)
{
switch (type) {
#ifdef R_X86_64_64
case R_X86_64_64:
return sizeof(uint64_t);
#endif
#ifdef R_X86_64_32
case R_X86_64_32:
return sizeof(uint32_t);
#endif
#ifdef RELOC_32
case RELOC_32:
return sizeof(uint32_t);
#endif
default:
break;
}
return -1;
}
#define ELF_WRITE_RELOC(buf, val, rsize) \
do { \
if (rsize == 4) { \
uint32_t v32 = val; \
memcpy(buf, &v32, sizeof(v32)); \
} else { \
uint64_t v64 = val; \
memcpy(buf, &v64, sizeof(v64)); \
} \
} while (0)
static void
elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
ssize_t sidx, char *sdata, size_t ssz)
{
Elf_Ehdr *eh = (Elf_Ehdr *)p;
Elf_Shdr *sh;
Elf_Rel *rel = NULL;
Elf_RelA *rela = NULL;
const Elf_Sym *symtab, *sym;
ssize_t symtabidx;
size_t nsymb, rsym, rtyp, roff;
size_t i, j;
uint64_t value;
int rsize;
/* Find symbol table location and number of symbols. */
symtabidx = elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb);
if (symtabidx == -1) {
warnx("symbol table not found");
return;
}
/* Apply possible relocation. */
for (i = 0; i < eh->e_shnum; i++) {
sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
if (sh->sh_size == 0)
continue;
if ((sh->sh_info != sidx) || (sh->sh_link != symtabidx))
continue;
switch (sh->sh_type) {
case SHT_RELA:
rela = (Elf_RelA *)(p + sh->sh_offset);
for (j = 0; j < (sh->sh_size / sizeof(Elf_RelA)); j++) {
rsym = ELF_R_SYM(rela[j].r_info);
rtyp = ELF_R_TYPE(rela[j].r_info);
roff = rela[j].r_offset;
if (rsym >= nsymb)
continue;
sym = &symtab[rsym];
value = sym->st_value + rela[j].r_addend;
rsize = elf_reloc_size(rtyp);
if (rsize == -1 || roff + rsize >= ssz)
continue;
ELF_WRITE_RELOC(sdata + roff, value, rsize);
}
break;
case SHT_REL:
rel = (Elf_Rel *)(p + sh->sh_offset);
for (j = 0; j < (sh->sh_size / sizeof(Elf_Rel)); j++) {
rsym = ELF_R_SYM(rel[j].r_info);
rtyp = ELF_R_TYPE(rel[j].r_info);
roff = rel[j].r_offset;
if (rsym >= nsymb)
continue;
sym = &symtab[rsym];
value = sym->st_value;
rsize = elf_reloc_size(rtyp);
if (rsize == -1 || roff + rsize >= ssz)
continue;
ELF_WRITE_RELOC(sdata + roff, value, rsize);
}
break;
default:
continue;
}
}
}

View file

@ -15,7 +15,7 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
VERSION = 1.14.3
VERSION = 1.14.2
# === LIST OF FILES ====================================================

View file

@ -2,21 +2,6 @@ $Id: NEWS,v 1.26 2017/07/28 14:57:56 schwarze Exp $
This file lists the most important changes in the mandoc.bsd.lv distribution.
Changes in version 1.14.3, released on August 5, 2017
--- BUG FIXES ---
* man(7): Do not crash with out-of-bounds read access to a constant
array if .sp or a blank line immediately precedes .SS or .SH.
* mdoc(7): Do not crash with out-of-bounds read access to a constant
array if .sp or a blank line precede the first .Sh macro.
* tbl(7): Ignore explicitly specified negative column widths rather than
wrapping around to huge numbers and risking memory exhaustion.
* man(1): No longer use names that only occur in the SYNOPSIS section.
Gets rid of some surprising behaviour and bogus warnings.
--- THANKS TO ---
Leah Neukirchen (Void Linux), Markus Waldeck (Debian),
Peter Bui (nd.edu), and Yuri Pankov (illumos) for bug reports.
Changes in version 1.14.2, released on July 28, 2017
--- MAJOR NEW FEATURES ---

View file

@ -1,4 +1,4 @@
/* $Id: man_term.c,v 1.209 2017/07/31 15:19:06 schwarze Exp $ */
/* $Id: man_term.c,v 1.208 2017/06/25 11:42:02 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -673,7 +673,7 @@ pre_SS(DECL_ARGS)
do {
n = n->prev;
} while (n != NULL && n->tok >= MAN_TH &&
} while (n != NULL && n->tok != TOKEN_NONE &&
termacts[n->tok].flags & MAN_NOTEXT);
if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL))
break;
@ -735,7 +735,7 @@ pre_SH(DECL_ARGS)
do {
n = n->prev;
} while (n != NULL && n->tok >= MAN_TH &&
} while (n != NULL && n->tok != TOKEN_NONE &&
termacts[n->tok].flags & MAN_NOTEXT);
if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL))
break;

View file

@ -1,4 +1,4 @@
/* $Id: mansearch.c,v 1.76 2017/08/02 13:29:04 schwarze Exp $ */
/* $OpenBSD: mansearch.c,v 1.50 2016/07/09 15:23:36 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -171,9 +171,7 @@ mansearch(const struct mansearch *search,
page = dbm_page_get(rp->page);
if (lstmatch(search->sec, page->sect) == 0 ||
lstmatch(search->arch, page->arch) == 0 ||
(search->argmode == ARG_NAME &&
rp->bits <= (int32_t)(NAME_SYN & NAME_MASK)))
lstmatch(search->arch, page->arch) == 0)
continue;
if (res == NULL) {
@ -454,28 +452,14 @@ lstlen(const char *cp, size_t sep)
{
size_t sz;
for (sz = 0; *cp != '\0'; cp++) {
/* Skip names appearing only in the SYNOPSIS. */
if (*cp <= (char)(NAME_SYN & NAME_MASK)) {
while (*cp != '\0')
cp++;
continue;
}
/* Skip name class markers. */
if (*cp < ' ')
cp++;
/* Print a separator before each but the first string. */
if (sz)
sz += sep;
/* Copy one string. */
while (*cp != '\0') {
sz++;
cp++;
}
for (sz = 0;; sz++) {
if (cp[0] == '\0') {
if (cp[1] == '\0')
break;
sz += sep - 1;
} else if (cp[0] < ' ')
sz--;
cp++;
}
return sz;
}
@ -487,34 +471,19 @@ lstlen(const char *cp, size_t sep)
static void
lstcat(char *buf, size_t *i, const char *cp, const char *sep)
{
const char *s;
size_t i_start;
const char *s;
for (i_start = *i; *cp != '\0'; cp++) {
/* Skip names appearing only in the SYNOPSIS. */
if (*cp <= (char)(NAME_SYN & NAME_MASK)) {
while (*cp != '\0')
cp++;
continue;
}
/* Skip name class markers. */
if (*cp < ' ')
cp++;
/* Print a separator before each but the first string. */
if (*i > i_start) {
for (;;) {
if (cp[0] == '\0') {
if (cp[1] == '\0')
break;
s = sep;
while (*s != '\0')
buf[(*i)++] = *s++;
}
/* Copy one string. */
while (*cp != '\0')
buf[(*i)++] = *cp++;
} else if (cp[0] >= ' ')
buf[(*i)++] = cp[0];
cp++;
}
}
/*

View file

@ -1,4 +1,4 @@
/* $Id: mdoc_validate.c,v 1.352 2017/08/02 13:29:04 schwarze Exp $ */
/* $Id: mdoc_validate.c,v 1.350 2017/07/20 12:54:02 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -1137,6 +1137,8 @@ post_fname(POST_ARGS)
if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*')))
mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse,
n->line, n->pos + pos, n->string);
if (n->sec == SEC_SYNOPSIS && mdoc->meta.msec != NULL)
mandoc_xr_add(mdoc->meta.msec, n->string, -1, -1);
}
static void
@ -1203,8 +1205,9 @@ post_nm(POST_ARGS)
n = mdoc->last;
if (n->sec == SEC_NAME && n->child != NULL &&
n->child->type == ROFFT_TEXT && mdoc->meta.msec != NULL)
if ((n->sec == SEC_NAME || n->sec == SEC_SYNOPSIS) &&
n->child != NULL && n->child->type == ROFFT_TEXT &&
mdoc->meta.msec != NULL)
mandoc_xr_add(mdoc->meta.msec, n->child->string, -1, -1);
if (n->last != NULL &&
@ -1928,7 +1931,7 @@ post_root(POST_ARGS)
/* Check that we begin with a proper `Sh'. */
n = mdoc->first->child;
while (n != NULL && n->tok >= MDOC_Dd &&
while (n != NULL && n->tok != TOKEN_NONE &&
mdoc_macros[n->tok].flags & MDOC_PROLOGUE)
n = n->next;

View file

@ -1,4 +1,4 @@
/* $Id: tbl_html.c,v 1.23 2017/07/31 16:14:10 schwarze Exp $ */
/* $Id: tbl_html.c,v 1.22 2017/06/12 20:14:18 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -49,9 +49,6 @@ html_tbl_strlen(const char *p, void *arg)
static size_t
html_tbl_sulen(const struct roffsu *su, void *arg)
{
if (su->scale < 0.0)
return 0;
switch (su->unit) {
case SCALE_FS: /* 2^16 basic units */
return su->scale * 65536.0 / 24.0;

View file

@ -1,4 +1,4 @@
/* $Id: tbl_term.c,v 1.57 2017/07/31 16:14:10 schwarze Exp $ */
/* $Id: tbl_term.c,v 1.56 2017/07/08 13:43:15 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011,2012,2014,2015,2017 Ingo Schwarze <schwarze@openbsd.org>
@ -51,10 +51,7 @@ static void tbl_word(struct termp *, const struct tbl_dat *);
static size_t
term_tbl_sulen(const struct roffsu *su, void *arg)
{
int i;
i = term_hen((const struct termp *)arg, su);
return i > 0 ? i : 0;
return term_hen((const struct termp *)arg, su);
}
static size_t