Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port libpulp to ppc64le #213

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/coding-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

steps:
- name: dependencies
run: zypper -n install clang git findutils
run: zypper -n install clang git findutils file
- uses: actions/checkout@v2
- name: format
run: find -type f \( -name "*.[c|h]" -or -name "*.cc" \) -exec clang-format -style=file -i {} \;
Expand Down
65 changes: 52 additions & 13 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ AC_INIT([libpulp],[0.3.6],[[email protected]])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_MACRO_DIRS([config])

# For multiarch builds.
AC_CANONICAL_TARGET

# Check for the availability of macros from autoconf-archive.
AC_MSG_CHECKING([autoconf-archive availability])
m4_ifndef([AX_CHECK_COMPILE_FLAG], [ax_available="no"])
Expand Down Expand Up @@ -133,12 +136,6 @@ AX_PYTHON_MODULE([psutil], [fatal])
AC_SUBST([AM_CFLAGS], ["-Wall -Wextra -Werror"])
AC_SUBST([AM_CCASFLAGS], ["-Wa,--fatal-warnings"])

# Use the glibc versions installed on path
AC_ARG_WITH([glibc],
AS_HELP_STRING([--with-glibc=GLIBC_PATH],[Use the glibc installed on GLIBC_PATH, where the .so file is present]),
[AC_SUBST([AM_LDFLAGS], ["-Wl,--dynamic-linker=$with_glibc/ld-linux-x86-64.so.2 -Wl,--rpath=$with_glibc/"])],
[])

# Checking the call stack of all threads enables libpulp to only apply a live
# patch when no threads sit within the target library.
AC_ARG_ENABLE(stack-check,
Expand Down Expand Up @@ -220,18 +217,60 @@ AC_SUBST([PAGE_SIZE], [$($GETCONF PAGE_SIZE)]))
# before the entry point, and the remaining nops after it. At running time,
# whenever a live patch is applied, libpulp replaces the remaining nops with
# instructions that redirect execution to the universe handling routines.
AC_SUBST([ULP_NOPS_LEN], [16])
AC_SUBST([PRE_NOPS_LEN], [14])

AC_SUBST([ULP_NOPS_LEN_ENDBR64], [$(expr $ULP_NOPS_LEN + 4)])
AC_SUBST([PRE_NOPS_LEN_ENDBR64], [$(expr $PRE_NOPS_LEN + 4)])
_NOPS_LEN=0
_PRE_NOPS_LEN=0

_LD_LINUX=""
AS_CASE([$target_cpu],
[x86_64],
[
_NOPS_LEN=16
_PRE_NOPS_LEN=14
_LD_LINUX="ld-linux-x86-64.so.2"
_PROC="x86_64"
],
[powerpc64le],
[
_NOPS_LEN=17
_PRE_NOPS_LEN=16
_LD_LINUX="ld64.so.2"
_PROC="powerpc64le"
]
)

AC_SUBST([ULP_NOPS_LEN], [$_NOPS_LEN])
AC_SUBST([PRE_NOPS_LEN], [$_PRE_NOPS_LEN])

AC_DEFINE_UNQUOTED([ULP_NOPS_LEN], [$ULP_NOPS_LEN],
[Total number of padding nops])
AC_DEFINE_UNQUOTED([PRE_NOPS_LEN], [$PRE_NOPS_LEN],
[Padding nops before the entry point of functions])
AC_DEFINE_UNQUOTED([ULP_NOPS_LEN_ENDBR64], [$ULP_NOPS_LEN_ENDBR64],
[Total number of padding nops when endbr64 is issued])

AC_DEFINE_UNQUOTED([LD_LINUX], ["$_LD_LINUX"],
[Path to the ld-linux loader] )

# Workaround a bug in autoconf 2.69
AM_CONDITIONAL([CPU_X86_64], [test "$_PROC" == "x86_64"])
AM_CONDITIONAL([CPU_PPC64LE], [test "$_PROC" == "powerpc64le"])

# Use the glibc versions installed on path
AC_ARG_WITH([glibc],
AS_HELP_STRING([--with-glibc=GLIBC_PATH],[Use the glibc installed on GLIBC_PATH, where the .so file is present]),
[AC_SUBST([AM_LDFLAGS], ["-Wl,--dynamic-linker=$with_glibc/$_LD_LINUX -Wl,--rpath=$with_glibc/"])],
[])

# Check if -fpatchable-function-entry=$ULP_NOPS_LEN,$RE_NOPS_LEN works
# correctly.
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[extern void g(void);
__attribute__((patchable_function_entry($_NOPS_LEN, $_PRE_NOPS_LEN)))
void f(void) { g(); }]])],
[patchable_works=yes],
[patchable_works=no])

AS_IF([test "x$patchable_works" == "xno"],
AC_MSG_ERROR(
[The -fpatchable-functions-entry flag of your C compiler does not work correctly]))

AC_CONFIG_FILES([Makefile
include/Makefile
Expand Down
11 changes: 11 additions & 0 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,14 @@ noinst_HEADERS = \
terminal_colors.h \
ld_rtld.h \
insn_queue.h

# Workaround a bug in Autoconf 2.69
if CPU_X86_64
noinst_HEADERS += \
arch/x86_64/arch_common.h
endif

if CPU_PPC64LE
noinst_HEADERS += \
arch/powerpc64le/arch_common.h
endif
34 changes: 34 additions & 0 deletions include/arch/powerpc64le/arch_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef _ARCH_PPC64LE_H
#define _ARCH_PPC64LE_H

/** Offset of TLS pointer. */
#define TLS_DTV_OFFSET 0x8000

/** Struct used to store the registers in memory. */
typedef struct pt_regs registers_t;

/** Register in which the function stores the return value. */
#define FUNCTION_RETURN_REG(reg) ((reg).gpr[3])

/** Register which acts as a program counter. */
#define PROGRAM_COUNTER_REG(reg) ((reg).nip)

/** Register which acts as top of stack. */
#define STACK_TOP_REG(reg) ((reg).gpr[1])

/** Set the GLOBAL ENTRYPOINT REGISTER, which in power is r12. */
#define SET_GLOBAL_ENTRYPOINT_REG(reg, val) (reg).gpr[12] = (val)

/* Program load bias, which can be recovered by running `ld --verbose`. */
#define EXECUTABLE_START 0x10000000UL

/* The Red zone. */
#define RED_ZONE_LEN 512

/**
* Number of bytes that the kernel subtracts from the program counter,
* when an ongoing syscall gets interrupted and must be restarted.
*/
#define RESTART_SYSCALL_SIZE 0

#endif
37 changes: 37 additions & 0 deletions include/arch/x86_64/arch_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef _ARCH_X86_64_H
#define _ARCH_X86_64_H

/** Intel endbr64 instruction optcode. */
#define INSN_ENDBR64 0xf3, 0x0f, 0x1e, 0xfa
giulianobelinassi marked this conversation as resolved.
Show resolved Hide resolved

/** Offset of TLS pointer. */
#define TLS_DTV_OFFSET 0

/** Struct used to store the registers in memory. */
typedef struct user_regs_struct registers_t;

/** Register in which the function stores the return value. */
#define FUNCTION_RETURN_REG(reg) ((reg).rax)

/** Register which acts as a program counter. */
#define PROGRAM_COUNTER_REG(reg) ((reg).rip)

/** Register which acts as top of stack. */
#define STACK_TOP_REG(reg) ((reg).rsp)

/** Set the GLOBAL ENTRYPOINT REGISTER, which in x86_64 doesn't exist. */
#define SET_GLOBAL_ENTRYPOINT_REG(reg, val)

/** Program load bias, which can be recovered by running `ld --verbose`. */
#define EXECUTABLE_START 0x400000UL

/** The red zone. */
#define RED_ZONE_LEN 128

/**
* Number of bytes that the kernel subtracts from the program counter,
* when an ongoing syscall gets interrupted and must be restarted.
*/
#define RESTART_SYSCALL_SIZE 2

#endif
2 changes: 2 additions & 0 deletions include/ulp.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ int __ulp_apply_patch();
void __ulp_print();

/* functions */
void *memwrite(void *dest, const void *src, size_t n);

void free_metadata(struct ulp_metadata *ulp);

int unload_handlers(struct ulp_metadata *ulp);
Expand Down
1 change: 0 additions & 1 deletion include/ulp_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
* scenarios. */
#define ULP_METADATA_BUF_LEN (512 * 1024)
#define ULP_PATH_LEN 256
#define RED_ZONE_LEN 128

#define ARRAY_LENGTH(v) (sizeof(v) / sizeof(*(v)))

Expand Down
30 changes: 24 additions & 6 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,37 @@ libpulp_la_SOURCES = \
ulp.c \
interpose.c \
msg_queue.c \
error.c \
ulp_prologue.S \
ulp_interface.S
libpulp_la_DEPENDENCIES= libpulp.versions
error.c

libpulp_la_LDFLAGS = \
-ldl \
-l:ld-linux-x86-64.so.2 \
-Wl,--version-script=$(srcdir)/libpulp.versions \
-Wl,--hash-style=sysv \ # Ubuntu seems to default to gnu, so be clear we ...
$(AM_LDFLAGS) # ... want old style hash sections, else DT_HASH is empty.

# Workaround a bug in Autoconf 2.69
if CPU_X86_64
libpulp_la_SOURCES += \
arch/x86_64/ulp_interface.S \
arch/x86_64/patch.c

libpulp_la_LDFLAGS += \
-l:ld-linux-x86-64.so.2
endif

if CPU_PPC64LE
libpulp_la_SOURCES += \
arch/powerpc64le/ulp_interface.S \
arch/powerpc64le/patch.c

libpulp_la_LDFLAGS += \
-l:ld64.so.2
endif

libpulp_la_DEPENDENCIES= libpulp.versions

libpulp_la_LIBADD = $(top_builddir)/common/libcommon.la

AM_CFLAGS += -I$(top_srcdir)/include
AM_CFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/include/arch/$(target_cpu)

EXTRA_DIST = libpulp.versions
Loading
Loading