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