sync with OpenBSD -current
This commit is contained in:
parent
25869dc67a
commit
14b4e966dd
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2012-2020 Alexander Bluhm <bluhm@openbsd.org>
|
Copyright (c) 2012-2024 Alexander Bluhm <bluhm@openbsd.org>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $OpenBSD: Makefile,v 1.29 2023/09/08 21:15:02 bluhm Exp $
|
# $OpenBSD: Makefile,v 1.30 2024/03/12 21:31:29 bluhm Exp $
|
||||||
|
|
||||||
# The following ports must be installed:
|
# The following ports must be installed:
|
||||||
#
|
#
|
||||||
@ -88,7 +88,11 @@ stamp-pf: addr.py pf.conf
|
|||||||
FRAG6_SCRIPTS !!= cd ${.CURDIR} && ls -1 frag6*.py
|
FRAG6_SCRIPTS !!= cd ${.CURDIR} && ls -1 frag6*.py
|
||||||
|
|
||||||
run-stack-frag6_queuelimit.py:
|
run-stack-frag6_queuelimit.py:
|
||||||
# the stack does not limit the amount of fragments during reassembly
|
# stack does not limit the amount of fragments during reassembly
|
||||||
|
@echo DISABLED
|
||||||
|
|
||||||
|
run-pf-frag6_oversize.py run-pf-frag6_unfragsize.py:
|
||||||
|
# pf does not send icmp parameter problem, so test does not work
|
||||||
@echo DISABLED
|
@echo DISABLED
|
||||||
|
|
||||||
run-stack-frag6_doubleatomic.py: addr.py stamp-stack
|
run-stack-frag6_doubleatomic.py: addr.py stamp-stack
|
||||||
|
65
regress/sys/netinet6/frag6/frag6_oversize.py
Normal file
65
regress/sys/netinet6/frag6/frag6_oversize.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/local/bin/python3
|
||||||
|
|
||||||
|
print("ping6 fragments in total larger than IP maximum packet")
|
||||||
|
|
||||||
|
# |---------|
|
||||||
|
# |--------|
|
||||||
|
# ... ...
|
||||||
|
# |--------|
|
||||||
|
|
||||||
|
import os
|
||||||
|
from addr import *
|
||||||
|
from scapy.all import *
|
||||||
|
|
||||||
|
pid=os.getpid()
|
||||||
|
eid=pid & 0xffff
|
||||||
|
payload=b"ABCDEFGHIJKLMNOP"
|
||||||
|
packet=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \
|
||||||
|
ICMPv6EchoRequest(id=eid, data=4095*payload)
|
||||||
|
plen=IPv6(raw(packet)).plen
|
||||||
|
print("plen=%u" % (plen))
|
||||||
|
if plen != 0xfff8:
|
||||||
|
print("PLEN!=%u" % (0xfff8))
|
||||||
|
exit(2)
|
||||||
|
bytes=bytes(packet)+b"12345678"
|
||||||
|
|
||||||
|
frag=[]
|
||||||
|
fid=pid & 0xffffffff
|
||||||
|
frag.append(IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10])
|
||||||
|
off=2**7
|
||||||
|
while off < 2**13:
|
||||||
|
frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \
|
||||||
|
bytes[40+off*8:40+off*8+2**10])
|
||||||
|
off+=2**7
|
||||||
|
eth=[]
|
||||||
|
for f in frag:
|
||||||
|
pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f
|
||||||
|
eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt)
|
||||||
|
|
||||||
|
if os.fork() == 0:
|
||||||
|
time.sleep(1)
|
||||||
|
sendp(eth, iface=LOCAL_IF)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
|
ans=sniff(iface=LOCAL_IF, timeout=3, filter=
|
||||||
|
"ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6")
|
||||||
|
for a in ans:
|
||||||
|
print("type %d" % (a.payload.payload.type))
|
||||||
|
print("icmp %s" % (icmp6types[a.payload.payload.type]))
|
||||||
|
if a and a.type == ETH_P_IPV6 and \
|
||||||
|
ipv6nh[a.payload.nh] == 'ICMPv6' and \
|
||||||
|
icmp6types[a.payload.payload.type] == 'Parameter problem':
|
||||||
|
print("code=%u" % (a.payload.payload.code))
|
||||||
|
# 0: 'erroneous header field encountered'
|
||||||
|
if a.payload.payload.code != 0:
|
||||||
|
print("WRONG PARAMETER PROBLEM CODE")
|
||||||
|
exit(1)
|
||||||
|
ptr=a.payload.payload.ptr
|
||||||
|
print("ptr=%u" % (ptr))
|
||||||
|
# 42: sizeof IPv6 header + offset in fragment header
|
||||||
|
if ptr != 42:
|
||||||
|
print("PTR!=%u" % (ptr))
|
||||||
|
exit(1)
|
||||||
|
exit(0)
|
||||||
|
print("NO ICMP PARAMETER PROBLEM")
|
||||||
|
exit(2)
|
77
regress/sys/netinet6/frag6/frag6_unfragsize.py
Normal file
77
regress/sys/netinet6/frag6/frag6_unfragsize.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/local/bin/python3
|
||||||
|
|
||||||
|
print("ping6 fragments with options total larger than IP maximum packet")
|
||||||
|
|
||||||
|
# |--------|
|
||||||
|
# ... ...
|
||||||
|
# |--------|
|
||||||
|
# drop first fragment with ECN conflict, reinsert with longer unfrag part
|
||||||
|
# |---------|
|
||||||
|
# HopByHop|---------|
|
||||||
|
|
||||||
|
import os
|
||||||
|
from addr import *
|
||||||
|
from scapy.all import *
|
||||||
|
|
||||||
|
pid=os.getpid()
|
||||||
|
eid=pid & 0xffff
|
||||||
|
payload=b"ABCDEFGHIJKLMNOP"
|
||||||
|
packet=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \
|
||||||
|
ICMPv6EchoRequest(id=eid, data=4095*payload)
|
||||||
|
plen=IPv6(raw(packet)).plen
|
||||||
|
print("plen=%u" % (plen))
|
||||||
|
if plen != 0xfff8:
|
||||||
|
print("PLEN!=%u" % (0xfff8))
|
||||||
|
exit(2)
|
||||||
|
bytes=bytes(packet)
|
||||||
|
|
||||||
|
frag=[]
|
||||||
|
fid=pid & 0xffffffff
|
||||||
|
off=2**7
|
||||||
|
while off < 2**13:
|
||||||
|
frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \
|
||||||
|
bytes[40+off*8:40+off*8+2**10])
|
||||||
|
off+=2**7
|
||||||
|
eth=[]
|
||||||
|
for f in frag:
|
||||||
|
pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f
|
||||||
|
eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt)
|
||||||
|
|
||||||
|
# first fragment with ECN to be dropped
|
||||||
|
eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/
|
||||||
|
IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6, tc=3)/
|
||||||
|
IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10])
|
||||||
|
|
||||||
|
# resend first fragment with unfragmentable part too long for IP plen
|
||||||
|
eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/
|
||||||
|
IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/
|
||||||
|
IPv6ExtHdrHopByHop(options=PadN(optdata="\0"*4))/
|
||||||
|
IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10])
|
||||||
|
|
||||||
|
if os.fork() == 0:
|
||||||
|
time.sleep(1)
|
||||||
|
sendp(eth, iface=LOCAL_IF)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
|
ans=sniff(iface=LOCAL_IF, timeout=3, filter=
|
||||||
|
"ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6")
|
||||||
|
for a in ans:
|
||||||
|
print("type %d" % (a.payload.payload.type))
|
||||||
|
print("icmp %s" % (icmp6types[a.payload.payload.type]))
|
||||||
|
if a and a.type == ETH_P_IPV6 and \
|
||||||
|
ipv6nh[a.payload.nh] == 'ICMPv6' and \
|
||||||
|
icmp6types[a.payload.payload.type] == 'Parameter problem':
|
||||||
|
print("code=%u" % (a.payload.payload.code))
|
||||||
|
# 0: 'erroneous header field encountered'
|
||||||
|
if a.payload.payload.code != 0:
|
||||||
|
print("WRONG PARAMETER PROBLEM CODE")
|
||||||
|
exit(1)
|
||||||
|
ptr=a.payload.payload.ptr
|
||||||
|
print("ptr=%u" % (ptr))
|
||||||
|
# 42: sizeof IPv6 header + offset in fragment header
|
||||||
|
if ptr != 42:
|
||||||
|
print("PTR!=%u" % (ptr))
|
||||||
|
exit(1)
|
||||||
|
exit(0)
|
||||||
|
print("NO ICMP PARAMETER PROBLEM")
|
||||||
|
exit(2)
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: gadget.S,v 1.1 2023/01/09 11:50:01 anton Exp $ */
|
/* $OpenBSD: gadget.S,v 1.2 2024/03/13 11:18:42 kettenis Exp $ */
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <machine/asm.h>
|
#include <machine/asm.h>
|
||||||
@ -12,11 +12,13 @@
|
|||||||
.type gadget_getpid,_ASM_TYPE_FUNCTION
|
.type gadget_getpid,_ASM_TYPE_FUNCTION
|
||||||
gadget_getpid:
|
gadget_getpid:
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
|
endbr64
|
||||||
mov $SYS_getpid, %eax
|
mov $SYS_getpid, %eax
|
||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
ldr x8, #SYS_getpid
|
bti c
|
||||||
|
mov x8, #SYS_getpid
|
||||||
svc 0
|
svc 0
|
||||||
dsb nsh
|
dsb nsh
|
||||||
isb
|
isb
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: machdep.c,v 1.86 2024/02/21 01:45:14 dlg Exp $ */
|
/* $OpenBSD: machdep.c,v 1.87 2024/03/13 14:57:08 kettenis Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
|
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
|
||||||
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
|
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
|
||||||
@ -366,6 +366,7 @@ cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
|
|||||||
return sysctl_rdquad(oldp, oldlenp, newp, value);
|
return sysctl_rdquad(oldp, oldlenp, newp, value);
|
||||||
case CPU_ID_AA64PFR1:
|
case CPU_ID_AA64PFR1:
|
||||||
value = 0;
|
value = 0;
|
||||||
|
value |= cpu_id_aa64pfr1 & ID_AA64PFR1_BT_MASK;
|
||||||
value |= cpu_id_aa64pfr1 & ID_AA64PFR1_SBSS_MASK;
|
value |= cpu_id_aa64pfr1 & ID_AA64PFR1_SBSS_MASK;
|
||||||
return sysctl_rdquad(oldp, oldlenp, newp, value);
|
return sysctl_rdquad(oldp, oldlenp, newp, value);
|
||||||
case CPU_ID_AA64ISAR2:
|
case CPU_ID_AA64ISAR2:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $OpenBSD: GENERIC,v 1.294 2024/03/10 13:25:10 jsg Exp $
|
# $OpenBSD: GENERIC,v 1.295 2024/03/13 14:43:31 bluhm Exp $
|
||||||
#
|
#
|
||||||
# Machine-independent option; used by all architectures for their
|
# Machine-independent option; used by all architectures for their
|
||||||
# GENERIC kernel
|
# GENERIC kernel
|
||||||
@ -16,7 +16,7 @@ option KMEMSTATS # collect malloc(9) statistics
|
|||||||
option PTRACE # ptrace(2) system call
|
option PTRACE # ptrace(2) system call
|
||||||
|
|
||||||
#option KVA_GUARDPAGES # slow virtual address recycling (+ guarding)
|
#option KVA_GUARDPAGES # slow virtual address recycling (+ guarding)
|
||||||
#option POOL_DEBUG # pool corruption detection
|
option POOL_DEBUG # pool corruption detection
|
||||||
#option VFSLCKDEBUG # VFS locking checks
|
#option VFSLCKDEBUG # VFS locking checks
|
||||||
|
|
||||||
option CRYPTO # Cryptographic framework
|
option CRYPTO # Cryptographic framework
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: dt_prov_profile.c,v 1.6 2024/02/09 17:42:18 cheloha Exp $ */
|
/* $OpenBSD: dt_prov_profile.c,v 1.7 2024/03/13 13:13:57 bluhm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
|
* Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
|
||||||
@ -53,13 +53,13 @@ int
|
|||||||
dt_prov_profile_init(void)
|
dt_prov_profile_init(void)
|
||||||
{
|
{
|
||||||
dtpp_profile = dt_dev_alloc_probe("hz", "97", &dt_prov_profile);
|
dtpp_profile = dt_dev_alloc_probe("hz", "97", &dt_prov_profile);
|
||||||
dt_dev_register_probe(dtpp_profile);
|
|
||||||
if (dtpp_profile == NULL)
|
if (dtpp_profile == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
dt_dev_register_probe(dtpp_profile);
|
||||||
dtpp_interval = dt_dev_alloc_probe("hz", "1", &dt_prov_interval);
|
dtpp_interval = dt_dev_alloc_probe("hz", "1", &dt_prov_interval);
|
||||||
dt_dev_register_probe(dtpp_interval);
|
|
||||||
if (dtpp_interval == NULL)
|
if (dtpp_interval == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
dt_dev_register_probe(dtpp_interval);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: tmux.1,v 1.936 2024/02/13 08:10:23 nicm Exp $
|
.\" $OpenBSD: tmux.1,v 1.937 2024/03/13 11:25:50 nicm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
.\"
|
.\"
|
||||||
@ -14,7 +14,7 @@
|
|||||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: February 13 2024 $
|
.Dd $Mdocdate: March 13 2024 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1036,9 +1036,17 @@ The following commands are available to manage clients and sessions:
|
|||||||
.D1 Pq alias: Ic attach
|
.D1 Pq alias: Ic attach
|
||||||
If run from outside
|
If run from outside
|
||||||
.Nm ,
|
.Nm ,
|
||||||
create a new client in the current terminal and attach it to
|
attach to
|
||||||
|
.Ar target-session
|
||||||
|
in the current terminal.
|
||||||
|
.Ar target-session
|
||||||
|
must already exist - to create a new session, see the
|
||||||
|
.Ic new-session
|
||||||
|
command (with
|
||||||
|
.Fl A
|
||||||
|
to create or attach).
|
||||||
|
If used from inside, switch the currently attached session to
|
||||||
.Ar target-session .
|
.Ar target-session .
|
||||||
If used from inside, switch the current client.
|
|
||||||
If
|
If
|
||||||
.Fl d
|
.Fl d
|
||||||
is specified, any other clients attached to the session are detached.
|
is specified, any other clients attached to the session are detached.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ksyms.c,v 1.6 2023/11/10 18:56:21 jasper Exp $ */
|
/* $OpenBSD: ksyms.c,v 1.7 2024/03/12 17:22:24 cheloha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
|
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
|
||||||
@ -23,6 +23,7 @@
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <gelf.h>
|
#include <gelf.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -30,60 +31,149 @@
|
|||||||
|
|
||||||
#include "btrace.h"
|
#include "btrace.h"
|
||||||
|
|
||||||
struct syms {
|
struct sym {
|
||||||
int fd;
|
char *sym_name;
|
||||||
Elf *elf;
|
unsigned long sym_value; /* from st_value */
|
||||||
Elf_Scn *symtab;
|
unsigned long sym_size; /* from st_size */
|
||||||
size_t strtabndx, nsymb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int kelf_parse(struct syms *);
|
struct syms {
|
||||||
|
struct sym *table;
|
||||||
|
size_t nsymb;
|
||||||
|
};
|
||||||
|
|
||||||
|
int sym_compare_search(const void *, const void *);
|
||||||
|
int sym_compare_sort(const void *, const void *);
|
||||||
|
|
||||||
struct syms *
|
struct syms *
|
||||||
kelf_open(const char *path)
|
kelf_open(const char *path)
|
||||||
{
|
{
|
||||||
struct syms *syms;
|
char *name;
|
||||||
int error;
|
Elf *elf;
|
||||||
|
Elf_Data *data = NULL;
|
||||||
|
Elf_Scn *scn = NULL, *symtab;
|
||||||
|
GElf_Sym sym;
|
||||||
|
GElf_Shdr shdr;
|
||||||
|
size_t i, shstrndx, strtabndx = SIZE_MAX, symtab_size;
|
||||||
|
unsigned long diff;
|
||||||
|
struct sym *tmp;
|
||||||
|
struct syms *syms = NULL;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (elf_version(EV_CURRENT) == EV_NONE)
|
if (elf_version(EV_CURRENT) == EV_NONE)
|
||||||
errx(1, "elf_version: %s", elf_errmsg(-1));
|
errx(1, "elf_version: %s", elf_errmsg(-1));
|
||||||
|
|
||||||
if ((syms = calloc(1, sizeof(*syms))) == NULL)
|
fd = open(path, O_RDONLY);
|
||||||
err(1, NULL);
|
if (fd == -1) {
|
||||||
|
|
||||||
syms->fd = open(path, O_RDONLY);
|
|
||||||
if (syms->fd == -1) {
|
|
||||||
warn("open: %s", path);
|
warn("open: %s", path);
|
||||||
free(syms);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((syms->elf = elf_begin(syms->fd, ELF_C_READ, NULL)) == NULL) {
|
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
|
||||||
warnx("elf_begin: %s", elf_errmsg(-1));
|
warnx("elf_begin: %s", elf_errmsg(-1));
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_kind(syms->elf) != ELF_K_ELF)
|
if (elf_kind(elf) != ELF_K_ELF)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
error = kelf_parse(syms);
|
if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
|
||||||
if (error)
|
warnx("elf_getshdrstrndx: %s", elf_errmsg(-1));
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((scn = elf_nextscn(elf, scn)) != NULL) {
|
||||||
|
if (gelf_getshdr(scn, &shdr) != &shdr) {
|
||||||
|
warnx("elf_getshdr: %s", elf_errmsg(-1));
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if ((name = elf_strptr(elf, shstrndx, shdr.sh_name)) == NULL) {
|
||||||
|
warnx("elf_strptr: %s", elf_errmsg(-1));
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (strcmp(name, ELF_SYMTAB) == 0 &&
|
||||||
|
shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) {
|
||||||
|
symtab = scn;
|
||||||
|
symtab_size = shdr.sh_size / shdr.sh_entsize;
|
||||||
|
}
|
||||||
|
if (strcmp(name, ELF_STRTAB) == 0 &&
|
||||||
|
shdr.sh_type == SHT_STRTAB) {
|
||||||
|
strtabndx = elf_ndxscn(scn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (symtab == NULL) {
|
||||||
|
warnx("%s: %s: section not found", path, ELF_SYMTAB);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (strtabndx == SIZE_MAX) {
|
||||||
|
warnx("%s: %s: section not found", path, ELF_STRTAB);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = elf_rawdata(symtab, data);
|
||||||
|
if (data == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
||||||
return syms;
|
if ((syms = calloc(1, sizeof(*syms))) == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
syms->table = calloc(symtab_size, sizeof *syms->table);
|
||||||
|
if (syms->table == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
for (i = 0; i < symtab_size; i++) {
|
||||||
|
if (gelf_getsym(data, i, &sym) == NULL)
|
||||||
|
continue;
|
||||||
|
if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
|
||||||
|
continue;
|
||||||
|
name = elf_strptr(elf, strtabndx, sym.st_name);
|
||||||
|
if (name == NULL)
|
||||||
|
continue;
|
||||||
|
syms->table[syms->nsymb].sym_name = strdup(name);
|
||||||
|
if (syms->table[syms->nsymb].sym_name == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
syms->table[syms->nsymb].sym_value = sym.st_value;
|
||||||
|
syms->table[syms->nsymb].sym_size = sym.st_size;
|
||||||
|
syms->nsymb++;
|
||||||
|
}
|
||||||
|
tmp = reallocarray(syms->table, syms->nsymb, sizeof *syms->table);
|
||||||
|
if (tmp == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
syms->table = tmp;
|
||||||
|
|
||||||
|
/* Sort symbols in ascending order by address. */
|
||||||
|
qsort(syms->table, syms->nsymb, sizeof *syms->table, sym_compare_sort);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some functions, particularly those written in assembly, have an
|
||||||
|
* st_size of zero. We can approximate a size for these by assuming
|
||||||
|
* that they extend from their st_value to that of the next function.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < syms->nsymb; i++) {
|
||||||
|
if (syms->table[i].sym_size != 0)
|
||||||
|
continue;
|
||||||
|
/* Can't do anything for the last symbol. */
|
||||||
|
if (i + 1 == syms->nsymb)
|
||||||
|
continue;
|
||||||
|
diff = syms->table[i + 1].sym_value - syms->table[i].sym_value;
|
||||||
|
syms->table[i].sym_size = diff;
|
||||||
|
}
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
kelf_close(syms);
|
elf_end(elf);
|
||||||
return NULL;
|
close(fd);
|
||||||
|
return syms;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kelf_close(struct syms *syms)
|
kelf_close(struct syms *syms)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (syms == NULL)
|
if (syms == NULL)
|
||||||
return;
|
return;
|
||||||
elf_end(syms->elf);
|
|
||||||
close(syms->fd);
|
for (i = 0; i < syms->nsymb; i++)
|
||||||
|
free(syms->table[i].sym_name);
|
||||||
|
free(syms->table);
|
||||||
free(syms);
|
free(syms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,106 +181,46 @@ int
|
|||||||
kelf_snprintsym(struct syms *syms, char *str, size_t size, unsigned long pc,
|
kelf_snprintsym(struct syms *syms, char *str, size_t size, unsigned long pc,
|
||||||
unsigned long off)
|
unsigned long off)
|
||||||
{
|
{
|
||||||
GElf_Sym sym;
|
struct sym key = { .sym_value = pc + off };
|
||||||
Elf_Data *data = NULL;
|
struct sym *entry;
|
||||||
Elf_Addr offset, bestoff = 0;
|
Elf_Addr offset;
|
||||||
size_t i, bestidx = 0;
|
|
||||||
char *name;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
if (syms == NULL)
|
if (syms == NULL)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
data = elf_rawdata(syms->symtab, data);
|
entry = bsearch(&key, syms->table, syms->nsymb, sizeof *syms->table,
|
||||||
if (data == NULL)
|
sym_compare_search);
|
||||||
|
if (entry == NULL)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
|
||||||
for (i = 0; i < syms->nsymb; i++) {
|
offset = pc - (entry->sym_value + off);
|
||||||
if (gelf_getsym(data, i, &sym) == NULL)
|
|
||||||
continue;
|
|
||||||
if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
|
|
||||||
continue;
|
|
||||||
if (pc >= sym.st_value + off) {
|
|
||||||
if (pc < (sym.st_value + off + sym.st_size))
|
|
||||||
break;
|
|
||||||
/* Workaround for symbols w/o size, usually asm ones. */
|
|
||||||
if (sym.st_size == 0 && sym.st_value + off > bestoff) {
|
|
||||||
bestidx = i;
|
|
||||||
bestoff = sym.st_value + off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == syms->nsymb) {
|
|
||||||
if (bestidx == 0 || gelf_getsym(data, bestidx, &sym) == NULL)
|
|
||||||
goto fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = elf_strptr(syms->elf, syms->strtabndx, sym.st_name);
|
|
||||||
if (name != NULL)
|
|
||||||
cnt = snprintf(str, size, "\n%s", name);
|
|
||||||
else
|
|
||||||
cnt = snprintf(str, size, "\n0x%llx", sym.st_value);
|
|
||||||
if (cnt < 0)
|
|
||||||
return cnt;
|
|
||||||
|
|
||||||
offset = pc - (sym.st_value + off);
|
|
||||||
if (offset != 0) {
|
if (offset != 0) {
|
||||||
int l;
|
return snprintf(str, size, "\n%s+0x%llx",
|
||||||
|
entry->sym_name, (unsigned long long)offset);
|
||||||
l = snprintf(str + cnt, size > (size_t)cnt ? size - cnt : 0,
|
|
||||||
"+0x%llx", (unsigned long long)offset);
|
|
||||||
if (l < 0)
|
|
||||||
return l;
|
|
||||||
cnt += l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return snprintf(str, size, "\n%s", entry->sym_name);
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
return snprintf(str, size, "\n0x%lx", pc);
|
return snprintf(str, size, "\n0x%lx", pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
kelf_parse(struct syms *syms)
|
sym_compare_sort(const void *ap, const void *bp)
|
||||||
{
|
{
|
||||||
GElf_Shdr shdr;
|
const struct sym *a = ap, *b = bp;
|
||||||
Elf_Scn *scn, *scnctf;
|
|
||||||
char *name;
|
|
||||||
size_t shstrndx;
|
|
||||||
|
|
||||||
if (elf_getshdrstrndx(syms->elf, &shstrndx) != 0) {
|
if (a->sym_value < b->sym_value)
|
||||||
warnx("elf_getshdrstrndx: %s", elf_errmsg(-1));
|
return -1;
|
||||||
return 1;
|
return a->sym_value > b->sym_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
scn = scnctf = NULL;
|
int
|
||||||
while ((scn = elf_nextscn(syms->elf, scn)) != NULL) {
|
sym_compare_search(const void *keyp, const void *entryp)
|
||||||
if (gelf_getshdr(scn, &shdr) != &shdr) {
|
{
|
||||||
warnx("elf_getshdr: %s", elf_errmsg(-1));
|
const struct sym *entry = entryp, *key = keyp;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((name = elf_strptr(syms->elf, shstrndx,
|
if (key->sym_value < entry->sym_value)
|
||||||
shdr.sh_name)) == NULL) {
|
return -1;
|
||||||
warnx("elf_strptr: %s", elf_errmsg(-1));
|
return key->sym_value >= entry->sym_value + entry->sym_size;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(name, ELF_SYMTAB) == 0 &&
|
|
||||||
shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) {
|
|
||||||
syms->symtab = scn;
|
|
||||||
syms->nsymb = shdr.sh_size / shdr.sh_entsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(name, ELF_STRTAB) == 0 &&
|
|
||||||
shdr.sh_type == SHT_STRTAB) {
|
|
||||||
syms->strtabndx = elf_ndxscn(scn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syms->symtab == NULL)
|
|
||||||
warnx("symbol table not found");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user