xref: /linux/tools/testing/selftests/exec/load_address.c (revision 4b911a9690d72641879ea6d13cce1de31d346d79)
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(1);
47 
48 	ret = dl_iterate_phdr(ExtractStatistics, &extracted);
49 	if (ret != 1)
50 		ksft_exit_fail_msg("FAILED: dl_iterate_phdr\n");
51 
52 	if (extracted.alignment == 0)
53 		ksft_exit_fail_msg("FAILED: No alignment found\n");
54 	else if (extracted.alignment & (extracted.alignment - 1))
55 		ksft_exit_fail_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("FAILED: alignment = %llu, load_address = %llu\n",
60 				   extracted.alignment, extracted.load_address);
61 
62 	ksft_test_result_pass("Completed\n");
63 	ksft_finished();
64 }
65