| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // SPDX-License-Identifier: GPL-2.0-only
- #ifndef _GNU_SOURCE
- #define _GNU_SOURCE
- #endif
- #include <link.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include "kselftest.h"
- struct Statistics {
- unsigned long long load_address;
- unsigned long long alignment;
- bool interp;
- };
- int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data)
- {
- struct Statistics *stats = (struct Statistics *) data;
- int i;
- if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') {
- // Ignore headers from other than the executable.
- return 2;
- }
- stats->load_address = (unsigned long long) info->dlpi_addr;
- stats->alignment = 0;
- for (i = 0; i < info->dlpi_phnum; i++) {
- unsigned long long align;
- if (info->dlpi_phdr[i].p_type == PT_INTERP) {
- stats->interp = true;
- continue;
- }
- if (info->dlpi_phdr[i].p_type != PT_LOAD)
- continue;
- align = info->dlpi_phdr[i].p_align;
- if (align > stats->alignment)
- stats->alignment = align;
- }
- return 1; // Terminate dl_iterate_phdr.
- }
- int main(int argc, char **argv)
- {
- struct Statistics extracted = { };
- unsigned long long misalign, pow2;
- bool interp_needed;
- char buf[1024];
- FILE *maps;
- int ret;
- ksft_print_header();
- ksft_set_plan(4);
- /* Dump maps file for debugging reference. */
- maps = fopen("/proc/self/maps", "r");
- if (!maps)
- ksft_exit_fail_msg("FAILED: /proc/self/maps: %s\n", strerror(errno));
- while (fgets(buf, sizeof(buf), maps)) {
- ksft_print_msg("%s", buf);
- }
- fclose(maps);
- /* Walk the program headers. */
- ret = dl_iterate_phdr(ExtractStatistics, &extracted);
- if (ret != 1)
- ksft_exit_fail_msg("FAILED: dl_iterate_phdr\n");
- /* Report our findings. */
- ksft_print_msg("load_address=%#llx alignment=%#llx\n",
- extracted.load_address, extracted.alignment);
- /* If we're named with ".static." we expect no INTERP. */
- interp_needed = strstr(argv[0], ".static.") == NULL;
- /* Were we built as expected? */
- ksft_test_result(interp_needed == extracted.interp,
- "%s INTERP program header %s\n",
- interp_needed ? "Wanted" : "Unwanted",
- extracted.interp ? "seen" : "missing");
- /* Did we find an alignment? */
- ksft_test_result(extracted.alignment != 0,
- "Alignment%s found\n", extracted.alignment ? "" : " NOT");
- /* Is the alignment sane? */
- pow2 = extracted.alignment & (extracted.alignment - 1);
- ksft_test_result(pow2 == 0,
- "Alignment is%s a power of 2: %#llx\n",
- pow2 == 0 ? "" : " NOT", extracted.alignment);
- /* Is the load address aligned? */
- misalign = extracted.load_address & (extracted.alignment - 1);
- ksft_test_result(misalign == 0, "Load Address is %saligned (%#llx)\n",
- misalign ? "MIS" : "", misalign);
- ksft_finished();
- }
|