Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Fix ELF note parsing and recognize NT_GNU_ABI_TAG
jrmarino committed 8 years ago
commit 4e0b7dfd10a3636f2bc68a310e8b512918795c92
parent 636c182
2 files changed +63 -8
modified libpkg/pkg_elf.c
@@ -710,12 +710,17 @@ pkg_get_myarch_elfparse(char *dest, size_t sz)
	Elf_Note note;
	Elf_Scn *scn = NULL;
	int fd;
+
	int version_style = 1;
	char *src = NULL;
	char *osname;
	uint32_t version = 0;
	int ret = EPKG_OK;
	const char *arch, *abi, *endian_corres_str, *wordsize_corres_str, *fpu;
	const char *path;
+
	char invalid_osname[] = "Unknown";
+
	char *note_os[6] = {"Linux", "GNU", "Solaris", "FreeBSD", "NetBSD", "Syllable"};
+
	char *(*pnote_os)[6] = &note_os;
+
	uint32_t gnu_abi_tag[4];

	path = getenv("ABI_FILE");
	if (path == NULL)
@@ -768,8 +773,21 @@ pkg_get_myarch_elfparse(char *dest, size_t sz)
	while ((uintptr_t)src < ((uintptr_t)data->d_buf + data->d_size)) {
		memcpy(&note, src, sizeof(Elf_Note));
		src += sizeof(Elf_Note);
-
		if (note.n_type == NT_VERSION)
-
			break;
+
		if ((strncmp ((const char *) src, "FreeBSD", note.n_namesz) == 0) ||
+
		    (strncmp ((const char *) src, "DragonFly", note.n_namesz) == 0) ||
+
 		    (strncmp ((const char *) src, "NetBSD", note.n_namesz) == 0) ||
+
		    (note.n_namesz == 0)) {
+
			if (note.n_type == NT_VERSION) {
+
				version_style = 1;
+
				break;
+
			}
+
		}
+
		if (strncmp ((const char *) src, "GNU", note.n_namesz) == 0) {
+
			if (note.n_type == NT_GNU_ABI_TAG) {
+
				version_style = 2;
+
				break;
+
			}
+
		}
		src += roundup2(note.n_namesz + note.n_descsz, 4);
	}
	if ((uintptr_t)src >= ((uintptr_t)data->d_buf + data->d_size)) {
@@ -777,17 +795,52 @@ pkg_get_myarch_elfparse(char *dest, size_t sz)
		pkg_emit_error("failed to find the version elf note");
		goto cleanup;
	}
-
	osname = src;
-
	src += roundup2(note.n_namesz, 4);
-
	if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
-
		version = be32dec(src);
-
	else
-
		version = le32dec(src);
+
	if (version_style == 2) {
+
		/*
+
		 * NT_GNU_ABI_TAG
+
		 * Operating system (OS) ABI information.  The
+
		 * desc field contains 4 words:
+
		 * word 0: OS descriptor (ELF_NOTE_OS_LINUX, ELF_NOTE_OS_GNU, etc)
+
		 * word 1: major version of the ABI
+
		 * word 2: minor version of the ABI
+
		 * word 3: subminor version of the ABI
+
		 */
+
		src += roundup2(note.n_namesz, 4);
+
		if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) {
+
			for (int wdndx = 0; wdndx < 4; wdndx++) {
+
				gnu_abi_tag[wdndx] = be32dec(src);
+
				src += 4;
+
			}
+
		} else {
+
			for (int wdndx = 0; wdndx < 4; wdndx++) {
+
				gnu_abi_tag[wdndx] = le32dec(src);
+
				src += 4;
+
			}
+
		}
+
		if (gnu_abi_tag[0] < 6)
+
			osname = (*pnote_os)[gnu_abi_tag[0]];
+
		else
+
			osname = invalid_osname;
+
	} else {
+
		if (note.n_namesz == 0)
+
			osname = invalid_osname;
+
		else
+
			osname = src;
+
		src += roundup2(note.n_namesz, 4);
+
		if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
+
			version = be32dec(src);
+
		else
+
			version = le32dec(src);
+
	}

	wordsize_corres_str = elf_corres_to_string(wordsize_corres,
	    (int)elfhdr.e_ident[EI_CLASS]);

	arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
+
if (version_style == 2) {
+
	snprintf(dest, sz, "%s:%d.%d.%d", osname, gnu_abi_tag[1],
+
		 gnu_abi_tag[2], gnu_abi_tag[3]);
+
} else {
#if defined(__DragonFly__)
	snprintf(dest, sz, "%s:%d.%d",
	    osname, version / 100000, (((version / 100 % 1000)+1)/2)*2);
@@ -796,6 +849,7 @@ pkg_get_myarch_elfparse(char *dest, size_t sz)
#else
	snprintf(dest, sz, "%s:%d", osname, version / 100000);
#endif
+
}

	switch (elfhdr.e_machine) {
	case EM_ARM:
modified libpkg/private/elf_tables.h
@@ -73,6 +73,7 @@ static const struct _elf_corres os_corres[] = {

#define NT_VERSION	1
#define NT_ARCH	2
+
#define NT_GNU_ABI_TAG	1

/* All possibilities on FreeBSD as of 5/26/2014 */
struct arch_trans {