bionic: Refactor __get_elf_note()
Factor out generic __get_elf_note() logic and rename __get_elf_note() to
__find_elf_note(). Expose __get_elf_note() in libc/private/bionic_note.h
This will be used in the subsequent patch to test the presence of
NT_ANDROID_TYPE_PAD_SEGMENT note when loading segments.
Test: atest -c linker-unit-tests [Later patch]
Test: m && launch_cvd
Bug: 316403210
Change-Id: Ia7cb2f40b10cfaef402182a675087c8422b37e4d
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
diff --git a/libc/Android.bp b/libc/Android.bp
index d25671e..825b95b 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -222,6 +222,11 @@
name: "libc_bootstrap",
}
+filegroup {
+ name: "elf_note_sources",
+ srcs: ["bionic/elf_note.cpp"],
+}
+
// libc_init_static.cpp and libc_init_dynamic.cpp need to be built without stack protector.
// libc_init_static.cpp sets up TLS for static executables, and libc_init_dynamic.cpp initializes
// the stack protector global variable.
@@ -229,7 +234,10 @@
cc_library_static {
name: "libc_init_static",
defaults: ["libc_defaults"],
- srcs: ["bionic/libc_init_static.cpp"],
+ srcs: [
+ "bionic/libc_init_static.cpp",
+ ":elf_note_sources",
+ ],
cflags: [
"-fno-stack-protector",
diff --git a/libc/bionic/elf_note.cpp b/libc/bionic/elf_note.cpp
new file mode 100644
index 0000000..d5cd5de
--- /dev/null
+++ b/libc/bionic/elf_note.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * 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 OWNER 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 "platform/bionic/macros.h"
+#include "private/elf_note.h"
+
+#include <string.h>
+
+bool __get_elf_note(unsigned note_type, const char* note_name, const ElfW(Addr) note_addr,
+ const ElfW(Phdr)* phdr_note, const ElfW(Nhdr)** note_hdr,
+ const char** note_desc) {
+ if (phdr_note->p_type != PT_NOTE || !note_name || !note_addr) {
+ return false;
+ }
+
+ ElfW(Addr) p = note_addr;
+ ElfW(Addr) note_end = p + phdr_note->p_memsz;
+
+ while (p + sizeof(ElfW(Nhdr)) <= note_end) {
+ const ElfW(Nhdr)* note = reinterpret_cast<const ElfW(Nhdr)*>(p);
+ p += sizeof(ElfW(Nhdr));
+ const char* name = reinterpret_cast<const char*>(p);
+ p += align_up(note->n_namesz, 4);
+ const char* desc = reinterpret_cast<const char*>(p);
+ p += align_up(note->n_descsz, 4);
+ if (p > note_end) {
+ break;
+ }
+ if (note->n_type != note_type) {
+ continue;
+ }
+ size_t note_name_len = strlen(note_name) + 1;
+ if (note->n_namesz != note_name_len || strncmp(note_name, name, note_name_len) != 0) {
+ break;
+ }
+
+ *note_hdr = note;
+ *note_desc = desc;
+
+ return true;
+ }
+ return false;
+}
+
+bool __find_elf_note(unsigned int note_type, const char* note_name, const ElfW(Phdr)* phdr_start,
+ size_t phdr_ct, const ElfW(Nhdr)** note_hdr, const char** note_desc,
+ const ElfW(Addr) load_bias) {
+ for (size_t i = 0; i < phdr_ct; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_start[i];
+
+ ElfW(Addr) note_addr = load_bias + phdr->p_vaddr;
+ if (__get_elf_note(note_type, note_name, note_addr, phdr, note_hdr, note_desc)) {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index f46d702..00faa5b 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -51,6 +51,7 @@
#include "private/bionic_elf_tls.h"
#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
+#include "private/elf_note.h"
#include "pthread_internal.h"
#include "sys/system_properties.h"
#include "sysprop_helpers.h"
@@ -157,49 +158,12 @@
}
#ifdef __aarch64__
-static bool __get_elf_note(const ElfW(Phdr) * phdr_start, size_t phdr_ct,
- const ElfW(Addr) load_bias, unsigned desired_type,
- const char* desired_name, const ElfW(Nhdr) * *note_out,
- const char** desc_out) {
- for (size_t i = 0; i < phdr_ct; ++i) {
- const ElfW(Phdr)* phdr = &phdr_start[i];
- if (phdr->p_type != PT_NOTE) {
- continue;
- }
- ElfW(Addr) p = load_bias + phdr->p_vaddr;
- ElfW(Addr) note_end = load_bias + phdr->p_vaddr + phdr->p_memsz;
- while (p + sizeof(ElfW(Nhdr)) <= note_end) {
- const ElfW(Nhdr)* note = reinterpret_cast<const ElfW(Nhdr)*>(p);
- p += sizeof(ElfW(Nhdr));
- const char* name = reinterpret_cast<const char*>(p);
- p += align_up(note->n_namesz, 4);
- const char* desc = reinterpret_cast<const char*>(p);
- p += align_up(note->n_descsz, 4);
- if (p > note_end) {
- break;
- }
- if (note->n_type != desired_type) {
- continue;
- }
- size_t desired_name_len = strlen(desired_name);
- if (note->n_namesz != desired_name_len + 1 ||
- strncmp(desired_name, name, desired_name_len) != 0) {
- break;
- }
- *note_out = note;
- *desc_out = desc;
- return true;
- }
- }
- return false;
-}
-
static HeapTaggingLevel __get_memtag_level_from_note(const ElfW(Phdr) * phdr_start, size_t phdr_ct,
const ElfW(Addr) load_bias, bool* stack) {
const ElfW(Nhdr) * note;
const char* desc;
- if (!__get_elf_note(phdr_start, phdr_ct, load_bias, NT_ANDROID_TYPE_MEMTAG, "Android", ¬e,
- &desc)) {
+ if (!__find_elf_note(NT_ANDROID_TYPE_MEMTAG, "Android", phdr_start, phdr_ct, ¬e, &desc,
+ load_bias)) {
return M_HEAP_TAGGING_LEVEL_TBI;
}
@@ -210,7 +174,7 @@
note->n_descsz);
}
- // `desc` is always aligned due to ELF requirements, enforced in __get_elf_note().
+ // `desc` is always aligned due to ELF requirements, enforced in __find_elf_note().
ElfW(Word) note_val = *reinterpret_cast<const ElfW(Word)*>(desc);
*stack = (note_val & NT_MEMTAG_STACK) != 0;
diff --git a/libc/private/elf_note.h b/libc/private/elf_note.h
new file mode 100644
index 0000000..6a9399b
--- /dev/null
+++ b/libc/private/elf_note.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * 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 OWNER 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.
+ */
+
+#pragma once
+
+#include <elf.h>
+#include <link.h>
+
+// Get desired ELF note (Nhdr/desc) from mmapped PT_NOTE
+bool __get_elf_note(unsigned note_type, const char* note_name, const ElfW(Addr) note_addr,
+ const ElfW(Phdr)* phdr_note, const ElfW(Nhdr)** note_hdr,
+ const char** note_desc);
+
+// Search all mapped PT_NOTE's for the desired ELF note (Nhdr/desc)
+bool __find_elf_note(unsigned int note_type, const char* note_name, const ElfW(Phdr)* phdr_start,
+ size_t phdr_ct, const ElfW(Nhdr)** note_hdr, const char** note_desc,
+ const ElfW(Addr) load_bias);