| // SPDX-License-Identifier: GPL-2.0-only | |
| #ifndef _GNU_SOURCE | |
| #define _GNU_SOURCE | |
| #endif | |
| #include <link.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| struct Statistics { | |
| unsigned long long load_address; | |
| unsigned long long alignment; | |
| }; | |
| 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++) { | |
| if (info->dlpi_phdr[i].p_type != PT_LOAD) | |
| continue; | |
| if (info->dlpi_phdr[i].p_align > stats->alignment) | |
| stats->alignment = info->dlpi_phdr[i].p_align; | |
| } | |
| return 1; // Terminate dl_iterate_phdr. | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| struct Statistics extracted; | |
| unsigned long long misalign; | |
| int ret; | |
| ret = dl_iterate_phdr(ExtractStatistics, &extracted); | |
| if (ret != 1) { | |
| fprintf(stderr, "FAILED\n"); | |
| return 1; | |
| } | |
| if (extracted.alignment == 0) { | |
| fprintf(stderr, "No alignment found\n"); | |
| return 1; | |
| } else if (extracted.alignment & (extracted.alignment - 1)) { | |
| fprintf(stderr, "Alignment is not a power of 2\n"); | |
| return 1; | |
| } | |
| misalign = extracted.load_address & (extracted.alignment - 1); | |
| if (misalign) { | |
| printf("alignment = %llu, load_address = %llu\n", | |
| extracted.alignment, extracted.load_address); | |
| fprintf(stderr, "FAILED\n"); | |
| return 1; | |
| } | |
| fprintf(stderr, "PASS\n"); | |
| return 0; | |
| } |