Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152993402
D28342.id82885.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D28342.id82885.diff
View Options
Index: usr.bin/ldd/Makefile
===================================================================
--- usr.bin/ldd/Makefile
+++ usr.bin/ldd/Makefile
@@ -3,4 +3,6 @@
PROG?= ldd
SRCS= ldd.c
+LIBADD= elf
+
.include <bsd.prog.mk>
Index: usr.bin/ldd/ldd.c
===================================================================
--- usr.bin/ldd/ldd.c
+++ usr.bin/ldd/ldd.c
@@ -33,6 +33,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <sys/wait.h>
#include <machine/elf.h>
@@ -43,6 +44,9 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -259,179 +263,182 @@
exit(1);
}
+static bool
+is_pie(const char *fname, Elf *elf)
+{
+ GElf_Shdr shdr;
+ GElf_Dyn dyn;
+ Elf_Scn *scn;
+ Elf_Data *d;
+ u_int i;
+
+ scn = NULL;
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (false);
+ }
+
+ if (shdr.sh_type != SHT_DYNAMIC)
+ continue;
+
+ d = elf_getdata(scn, NULL);
+ if (d == NULL)
+ continue;
+
+ for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
+ if (gelf_getdyn(d, i, &dyn) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ break;
+ }
+
+ if (dyn.d_tag != DT_FLAGS_1)
+ continue;
+
+ return ((dyn.d_un.d_val & DF_1_PIE) != 0);
+ }
+ }
+
+ return (false);
+}
+
+static bool
+check_notes(const char *buf, size_t len)
+{
+ const Elf_Note *note;
+ const char *name;
+ size_t namesz, descsz;
+
+ for (;;) {
+ if (len < sizeof(*note))
+ return (false);
+ note = (const void *)buf;
+ buf += sizeof(*note);
+ len -= sizeof(*note);
+
+ namesz = roundup2(note->n_namesz, 4);
+ descsz = roundup2(note->n_descsz, 4);
+ if (len < namesz + descsz)
+ return (false);
+
+ name = buf;
+ if (strncmp(name, "FreeBSD", namesz) == 0 &&
+ note->n_type == NT_FREEBSD_ABI_TAG)
+ return (true);
+
+ buf += namesz + descsz;
+ len -= namesz + descsz;
+ }
+
+ return (false);
+}
+
+static bool
+is_freebsd_elf(const char *fname, Elf *elf, GElf_Ehdr *ehdr)
+{
+ GElf_Shdr shdr;
+ Elf_Scn *scn;
+ Elf_Data *d;
+
+ switch (ehdr->e_ident[EI_OSABI]) {
+ case ELFOSABI_FREEBSD:
+ return (true);
+ case ELFOSABI_NONE:
+ break;
+ default:
+ return (false);
+ }
+
+ scn = NULL;
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (false);
+ }
+
+ if (shdr.sh_type != SHT_NOTE)
+ continue;
+
+ d = elf_getdata(scn, NULL);
+ if (d == NULL)
+ continue;
+
+ if (check_notes(d->d_buf, d->d_size))
+ return (true);
+ }
+
+ return (false);
+}
+
static int
is_executable(const char *fname, int fd, int *is_shlib, int *type)
{
- union {
-#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
- Elf32_Ehdr elf32;
-#endif
- Elf_Ehdr elf;
- } hdr;
- Elf_Phdr phdr, dynphdr;
- Elf_Dyn *dynp;
- void *dyndata;
-#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
- Elf32_Phdr phdr32, dynphdr32;
- Elf32_Dyn *dynp32;
-#endif
- int df1pie, dynamic, i, n;
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Phdr phdr;
+ bool dynamic;
+ int i;
*is_shlib = 0;
*type = TYPE_UNKNOWN;
- df1pie = 0;
+ dynamic = false;
- if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
- warn("%s: can't read program header", fname);
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ warnx("unsupported libelf");
+ return (0);
+ }
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (elf == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (0);
+ }
+ if (elf_kind(elf) != ELF_K_ELF) {
+ elf_end(elf);
+ warnx("%s: not a dynamic ELF executable", fname);
+ return (0);
+ }
+ if (gelf_getehdr(elf, &ehdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ elf_end(elf);
return (0);
}
+ *type = TYPE_ELF;
#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
- if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
- hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
- /* Handle 32 bit ELF objects */
-
- dynamic = 0;
+ if (gelf_getclass(elf) == ELFCLASS32) {
*type = TYPE_ELF32;
-
- if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
- warnx("%s: header too short", fname);
- return (0);
- }
- for (i = 0; i < hdr.elf32.e_phnum; i++) {
- if (read(fd, &phdr32, hdr.elf32.e_phentsize) !=
- sizeof(phdr32)) {
- warnx("%s: can't read program header", fname);
- return (0);
- }
- if (phdr32.p_type == PT_DYNAMIC) {
- dynamic = 1;
- dynphdr32 = phdr32;
- break;
- }
- }
-
- if (!dynamic) {
- warnx("%s: not a dynamic ELF executable", fname);
- return (0);
- }
-
- if (hdr.elf32.e_type == ET_DYN) {
- if (lseek(fd, dynphdr32.p_offset, SEEK_SET) == -1) {
- warnx("%s: dynamic segment out of range",
- fname);
- return (0);
- }
- dyndata = malloc(dynphdr32.p_filesz);
- if (dyndata == NULL) {
- warn("malloc");
- return (0);
- }
- if (read(fd, dyndata, dynphdr32.p_filesz) !=
- (ssize_t)dynphdr32.p_filesz) {
- free(dyndata);
- warnx("%s: can't read dynamic segment", fname);
- return (0);
- }
- for (dynp32 = dyndata; dynp32->d_tag != DT_NULL;
- dynp32++) {
- if (dynp32->d_tag != DT_FLAGS_1)
- continue;
- df1pie = (dynp32->d_un.d_val & DF_1_PIE) != 0;
- break;
- }
- free(dyndata);
-
- if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
- if (!df1pie)
- *is_shlib = 1;
- return (1);
- }
- warnx("%s: not a FreeBSD ELF shared object", fname);
- return (0);
- }
-
- return (1);
}
#endif
- if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
- hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
- /* Handle default ELF objects on this architecture */
-
- dynamic = 0;
- *type = TYPE_ELF;
-
- if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
- warnx("%s: header too short", fname);
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ if (gelf_getphdr(elf, i, &phdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ elf_end(elf);
return (0);
}
- for (i = 0; i < hdr.elf.e_phnum; i++) {
- if (read(fd, &phdr, hdr.elf.e_phentsize)
- != sizeof(phdr)) {
- warnx("%s: can't read program header", fname);
- return (0);
- }
- if (phdr.p_type == PT_DYNAMIC) {
- dynamic = 1;
- dynphdr = phdr;
- break;
- }
+ switch (phdr.p_type) {
+ case PT_DYNAMIC:
+ dynamic = true;
+ break;
}
+ }
- if (!dynamic) {
- warnx("%s: not a dynamic ELF executable", fname);
- return (0);
- }
+ if (!dynamic) {
+ elf_end(elf);
+ warnx("%s: not a dynamic ELF executable", fname);
+ return (0);
+ }
- if (hdr.elf.e_type == ET_DYN) {
- if (lseek(fd, dynphdr.p_offset, SEEK_SET) == -1) {
- warnx("%s: dynamic segment out of range",
- fname);
- return (0);
- }
- dyndata = malloc(dynphdr.p_filesz);
- if (dyndata == NULL) {
- warn("malloc");
- return (0);
- }
- if (read(fd, dyndata, dynphdr.p_filesz) !=
- (ssize_t)dynphdr.p_filesz) {
- free(dyndata);
- warnx("%s: can't read dynamic segment", fname);
- return (0);
- }
- for (dynp = dyndata; dynp->d_tag != DT_NULL; dynp++) {
- if (dynp->d_tag != DT_FLAGS_1)
- continue;
- df1pie = (dynp->d_un.d_val & DF_1_PIE) != 0;
- break;
- }
- free(dyndata);
+ if (ehdr.e_type == ET_DYN && !is_pie(fname, elf)) {
+ *is_shlib = 1;
- switch (hdr.elf.e_ident[EI_OSABI]) {
- case ELFOSABI_FREEBSD:
- if (!df1pie)
- *is_shlib = 1;
- return (1);
-#ifdef __ARM_EABI__
- case ELFOSABI_NONE:
- if (hdr.elf.e_machine != EM_ARM)
- break;
- if (EF_ARM_EABI_VERSION(hdr.elf.e_flags) <
- EF_ARM_EABI_FREEBSD_MIN)
- break;
- *is_shlib = 1;
- return (1);
-#endif
- }
+ if (!is_freebsd_elf(fname, elf, &ehdr)) {
+ elf_end(elf);
warnx("%s: not a FreeBSD ELF shared object", fname);
return (0);
}
-
- return (1);
}
- warnx("%s: not a dynamic executable", fname);
- return (0);
+ elf_end(elf);
+ return (1);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 19, 12:48 PM (16 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31770873
Default Alt Text
D28342.id82885.diff (7 KB)
Attached To
Mode
D28342: Fix ldd to work with more ELF files.
Attached
Detach File
Event Timeline
Log In to Comment