1 // SPDX-License-Identifier: GPL-2.0-only 2 #ifndef _GNU_SOURCE 3 #define _GNU_SOURCE 4 #endif 5 #include <link.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdbool.h> 9 #include "../kselftest.h" 10 11 struct Statistics { 12 unsigned long long load_address; 13 unsigned long long alignment; 14 bool interp; 15 }; 16 17 int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data) 18 { 19 struct Statistics *stats = (struct Statistics *) data; 20 int i; 21 22 if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') { 23 // Ignore headers from other than the executable. 24 return 2; 25 } 26 27 stats->load_address = (unsigned long long) info->dlpi_addr; 28 stats->alignment = 0; 29 30 for (i = 0; i < info->dlpi_phnum; i++) { 31 unsigned long long align; 32 33 if (info->dlpi_phdr[i].p_type == PT_INTERP) { 34 stats->interp = true; 35 continue; 36 } 37 38 if (info->dlpi_phdr[i].p_type != PT_LOAD) 39 continue; 40 41 align = info->dlpi_phdr[i].p_align; 42 43 if (align > stats->alignment) 44 stats->alignment = align; 45 } 46 47 return 1; // Terminate dl_iterate_phdr. 48 } 49 50 int main(int argc, char **argv) 51 { 52 struct Statistics extracted = { }; 53 unsigned long long misalign, pow2; 54 bool interp_needed; 55 char buf[1024]; 56 FILE *maps; 57 int ret; 58 59 ksft_print_header(); 60 ksft_set_plan(4); 61 62 /* Dump maps file for debugging reference. */ 63 maps = fopen("/proc/self/maps", "r"); 64 if (!maps) 65 ksft_exit_fail_msg("FAILED: /proc/self/maps: %s\n", strerror(errno)); 66 while (fgets(buf, sizeof(buf), maps)) { 67 ksft_print_msg("%s", buf); 68 } 69 fclose(maps); 70 71 /* Walk the program headers. */ 72 ret = dl_iterate_phdr(ExtractStatistics, &extracted); 73 if (ret != 1) 74 ksft_exit_fail_msg("FAILED: dl_iterate_phdr\n"); 75 76 /* Report our findings. */ 77 ksft_print_msg("load_address=%#llx alignment=%#llx\n", 78 extracted.load_address, extracted.alignment); 79 80 /* If we're named with ".static." we expect no INTERP. */ 81 interp_needed = strstr(argv[0], ".static.") == NULL; 82 83 /* Were we built as expected? */ 84 ksft_test_result(interp_needed == extracted.interp, 85 "%s INTERP program header %s\n", 86 interp_needed ? "Wanted" : "Unwanted", 87 extracted.interp ? "seen" : "missing"); 88 89 /* Did we find an alignment? */ 90 ksft_test_result(extracted.alignment != 0, 91 "Alignment%s found\n", extracted.alignment ? "" : " NOT"); 92 93 /* Is the alignment sane? */ 94 pow2 = extracted.alignment & (extracted.alignment - 1); 95 ksft_test_result(pow2 == 0, 96 "Alignment is%s a power of 2: %#llx\n", 97 pow2 == 0 ? "" : " NOT", extracted.alignment); 98 99 /* Is the load address aligned? */ 100 misalign = extracted.load_address & (extracted.alignment - 1); 101 ksft_test_result(misalign == 0, "Load Address is %saligned (%#llx)\n", 102 misalign ? "MIS" : "", misalign); 103 104 ksft_finished(); 105 } 106