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 "../kselftest.h" |
9 | |
10 | struct Statistics { |
11 | unsigned long long load_address; |
12 | unsigned long long alignment; |
13 | }; |
14 | |
15 | int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data) |
16 | { |
17 | struct Statistics *stats = (struct Statistics *) data; |
18 | int i; |
19 | |
20 | if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') { |
21 | // Ignore headers from other than the executable. |
22 | return 2; |
23 | } |
24 | |
25 | stats->load_address = (unsigned long long) info->dlpi_addr; |
26 | stats->alignment = 0; |
27 | |
28 | for (i = 0; i < info->dlpi_phnum; i++) { |
29 | if (info->dlpi_phdr[i].p_type != PT_LOAD) |
30 | continue; |
31 | |
32 | if (info->dlpi_phdr[i].p_align > stats->alignment) |
33 | stats->alignment = info->dlpi_phdr[i].p_align; |
34 | } |
35 | |
36 | return 1; // Terminate dl_iterate_phdr. |
37 | } |
38 | |
39 | int main(int argc, char **argv) |
40 | { |
41 | struct Statistics extracted; |
42 | unsigned long long misalign; |
43 | int ret; |
44 | |
45 | ksft_print_header(); |
46 | ksft_set_plan(plan: 1); |
47 | |
48 | ret = dl_iterate_phdr(ExtractStatistics, &extracted); |
49 | if (ret != 1) |
50 | ksft_exit_fail_msg(msg: "FAILED: dl_iterate_phdr\n"); |
51 | |
52 | if (extracted.alignment == 0) |
53 | ksft_exit_fail_msg(msg: "FAILED: No alignment found\n"); |
54 | else if (extracted.alignment & (extracted.alignment - 1)) |
55 | ksft_exit_fail_msg(msg: "FAILED: Alignment is not a power of 2\n"); |
56 | |
57 | misalign = extracted.load_address & (extracted.alignment - 1); |
58 | if (misalign) |
59 | ksft_exit_fail_msg(msg: "FAILED: alignment = %llu, load_address = %llu\n", |
60 | extracted.alignment, extracted.load_address); |
61 | |
62 | ksft_test_result_pass(msg: "Completed\n"); |
63 | ksft_finished(); |
64 | } |
65 |