libdrgn: add stub s390 and s390x architectures with relocation implementation

The only relocation type I saw in Debian's kernel module debug info was
R_390_32. R_390_8, R_390_16, R_390_64, R_390_PC16, R_390_PC32, and
R_390_PC64 are trivial to support, as well. The Linux kernel supports
many more, but hopefully they won't show up for debug info.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
Omar Sandoval 2021-12-03 02:57:34 -08:00
parent 6ad80feb83
commit 9ee1ccff98
7 changed files with 89 additions and 0 deletions

View File

@ -954,6 +954,12 @@ class Architecture(enum.Enum):
RISCV32 = ...
"""The 32-bit RISC-V architecture."""
S390X = ...
"""The s390x architecture, a.k.a. IBM Z or z/Architecture."""
S390 = ...
"""The 32-bit s390 architecture, a.k.a. System/390."""
UNKNOWN = ...
"""
An architecture which is not known to drgn. Certain features are not

View File

@ -35,6 +35,7 @@ libdrgnimpl_la_SOURCES = $(ARCH_DEFS_PYS:_defs.py=.c) \
arch_arm.c \
arch_i386.c \
arch_riscv.c \
arch_s390x.c \
array.h \
binary_buffer.c \
binary_buffer.h \

57
libdrgn/arch_s390x.c Normal file
View File

@ -0,0 +1,57 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "platform.h" // IWYU pragma: associated
static struct drgn_error *
apply_elf_reloc_s390(const struct drgn_relocating_section *relocating,
uint64_t r_offset, uint32_t r_type,
const int64_t *r_addend, uint64_t sym_value)
{
switch (r_type) {
case R_390_NONE:
return NULL;
case R_390_8:
return drgn_reloc_add8(relocating, r_offset, r_addend,
sym_value);
case R_390_16:
return drgn_reloc_add16(relocating, r_offset, r_addend,
sym_value);
case R_390_32:
return drgn_reloc_add32(relocating, r_offset, r_addend,
sym_value);
case R_390_PC32:
return drgn_reloc_add32(relocating, r_offset, r_addend,
sym_value
- (relocating->addr + r_offset));
case R_390_PC16:
return drgn_reloc_add16(relocating, r_offset, r_addend,
sym_value
- (relocating->addr + r_offset));
case R_390_64:
return drgn_reloc_add64(relocating, r_offset, r_addend,
sym_value);
case R_390_PC64:
return drgn_reloc_add64(relocating, r_offset, r_addend,
sym_value
- (relocating->addr + r_offset));
default:
return DRGN_UNKNOWN_RELOCATION_TYPE(r_type);
}
}
const struct drgn_architecture_info arch_info_s390x = {
.name = "s390x",
.arch = DRGN_ARCH_S390X,
.default_flags = DRGN_PLATFORM_IS_64_BIT,
.register_by_name = drgn_register_by_name_unknown,
.apply_elf_reloc = apply_elf_reloc_s390,
};
const struct drgn_architecture_info arch_info_s390 = {
.name = "s390",
.arch = DRGN_ARCH_S390,
.default_flags = 0,
.register_by_name = drgn_register_by_name_unknown,
.apply_elf_reloc = apply_elf_reloc_s390,
};

View File

@ -375,6 +375,8 @@ enum drgn_architecture {
DRGN_ARCH_PPC64,
DRGN_ARCH_RISCV64,
DRGN_ARCH_RISCV32,
DRGN_ARCH_S390X,
DRGN_ARCH_S390,
};
/** Flags describing a @ref drgn_platform. */

View File

@ -36,6 +36,10 @@ static struct drgn_error *drgn_platform_from_kdump(kdump_ctx_t *ctx,
else if (strcmp(str, KDUMP_ARCH_PPC64) == 0)
arch = &arch_info_ppc64;
/* libkdumpfile doesn't support RISC-V */
else if (strcmp(str, KDUMP_ARCH_S390X) == 0)
arch = &arch_info_s390x;
else if (strcmp(str, KDUMP_ARCH_S390) == 0)
arch = &arch_info_s390;
else
arch = &arch_info_unknown;

View File

@ -38,6 +38,11 @@ LIBDRGN_PUBLIC const struct drgn_platform drgn_host_platform = {
#else
#error "unknown __riscv_xlen"
#endif
#elif __s390x__
.arch = &arch_info_s390x,
// __s390__ is also defined for s390x, so the order is important.
#elif __s390__
.arch = &arch_info_s390,
#else
.arch = &arch_info_unknown,
#endif
@ -77,6 +82,12 @@ drgn_platform_create(enum drgn_architecture arch,
case DRGN_ARCH_RISCV32:
arch_info = &arch_info_riscv32;
break;
case DRGN_ARCH_S390X:
arch_info = &arch_info_s390x;
break;
case DRGN_ARCH_S390:
arch_info = &arch_info_s390;
break;
default:
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
"invalid architecture");
@ -162,6 +173,12 @@ void drgn_platform_from_elf(GElf_Ehdr *ehdr, struct drgn_platform *ret)
else
arch = &arch_info_riscv32;
break;
case EM_S390:
if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
arch = &arch_info_s390x;
else
arch = &arch_info_s390;
break;
default:
arch = &arch_info_unknown;
break;

View File

@ -372,6 +372,8 @@ extern const struct drgn_architecture_info arch_info_arm;
extern const struct drgn_architecture_info arch_info_ppc64;
extern const struct drgn_architecture_info arch_info_riscv64;
extern const struct drgn_architecture_info arch_info_riscv32;
extern const struct drgn_architecture_info arch_info_s390x;
extern const struct drgn_architecture_info arch_info_s390;
struct drgn_platform {
const struct drgn_architecture_info *arch;