Skip to content

Commit

Permalink
elf2dmp: introduce physical block alignment
Browse files Browse the repository at this point in the history
Physical memory ranges may not be aligned to page size in QEMU ELF, but
DMP can only contain page-aligned runs. So, align them.

Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-id: 20230915170153.10959-3-viktor@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
viktor-prutyanov authored and pm215 committed Sep 21, 2023
1 parent 3c407ec commit d5c27a5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
31 changes: 29 additions & 2 deletions contrib/elf2dmp/addrspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa)

for (i = 0; i < ps->block_nr; i++) {
if (ps->block[i].paddr <= pa &&
pa <= ps->block[i].paddr + ps->block[i].size) {
pa < ps->block[i].paddr + ps->block[i].size) {
return ps->block + i;
}
}
Expand All @@ -33,6 +33,30 @@ static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa)
return block->addr + (pa - block->paddr);
}

static void pa_block_align(struct pa_block *b)
{
uint64_t low_align = ((b->paddr - 1) | ELF2DMP_PAGE_MASK) + 1 - b->paddr;
uint64_t high_align = (b->paddr + b->size) & ELF2DMP_PAGE_MASK;

if (low_align == 0 && high_align == 0) {
return;
}

if (low_align + high_align < b->size) {
printf("Block 0x%"PRIx64"+:0x%"PRIx64" will be aligned to "
"0x%"PRIx64"+:0x%"PRIx64"\n", b->paddr, b->size,
b->paddr + low_align, b->size - low_align - high_align);
b->size -= low_align + high_align;
} else {
printf("Block 0x%"PRIx64"+:0x%"PRIx64" is too small to align\n",
b->paddr, b->size);
b->size = 0;
}

b->addr += low_align;
b->paddr += low_align;
}

int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
{
Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map);
Expand Down Expand Up @@ -60,10 +84,13 @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
.paddr = phdr[i].p_paddr,
.size = phdr[i].p_filesz,
};
block_i++;
pa_block_align(&ps->block[block_i]);
block_i = ps->block[block_i].size ? (block_i + 1) : block_i;
}
}

ps->block_nr = block_i;

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions contrib/elf2dmp/addrspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#define ELF2DMP_PAGE_BITS 12
#define ELF2DMP_PAGE_SIZE (1ULL << ELF2DMP_PAGE_BITS)
#define ELF2DMP_PAGE_MASK (ELF2DMP_PAGE_SIZE - 1)
#define ELF2DMP_PFN_MASK (~(ELF2DMP_PAGE_SIZE - 1))

#define INVALID_PA UINT64_MAX
Expand Down
5 changes: 3 additions & 2 deletions contrib/elf2dmp/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,10 @@ static int write_dump(struct pa_space *ps,
for (i = 0; i < ps->block_nr; i++) {
struct pa_block *b = &ps->block[i];

printf("Writing block #%zu/%zu to file...\n", i, ps->block_nr);
printf("Writing block #%zu/%zu of %"PRIu64" bytes to file...\n", i,
ps->block_nr, b->size);
if (fwrite(b->addr, b->size, 1, dmp_file) != 1) {
eprintf("Failed to write dump header\n");
eprintf("Failed to write block\n");
fclose(dmp_file);
return 1;
}
Expand Down

0 comments on commit d5c27a5

Please sign in to comment.