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

Remove host / target architecture assumption from create-diff-object #1248

Merged
merged 3 commits into from
Feb 4, 2022

Conversation

joe-lawrence
Copy link
Contributor

This is a remix of @gwelymernans 's #1179 with a few slight tweaks:

  1. Do not add an --arch command line argument to various tools and kpatch-build. Detect the ELF architecture of the input files and pivot based on that. This would allow for a (theoretical at this point) cross-arch-build to build a ppc64le reference/patched kernel and when processing its object files, rely on the ELF header to indicate the target architecture.
  2. Modifications limited to create-diff-object for now. Without testing full cross-arch-build support, this is still useful to the project as we can test the ppc64le unit tests (with a very small patch: unit-objs-cross.diff.txt):
$ arch
x86_64

$ make -s unit OBJDIR=objs/ppc64le
BUILD function-ptr-new
BUILD ASSERT_RTNL-detect
BUILD meminfo-init-FAIL
BUILD bug-table-section
BUILD smp-locks-section
BUILD fixup-section
BUILD meminfo-string
BUILD gcc-static-local-var-5
BUILD meminfo-init2-FAIL
BUILD gcc-static-local-var-3
BUILD mcount_loc-issue-1102
BUILD gcc-constprop-2-issue-935
BUILD ppc64le-bundled-localentry-issue-1007
BUILD static-local-size-mismatch-issue-1053
BUILD data-read-mostly
BUILD sec-addralign
BUILD tracepoints-section
BUILD data-rel
BUILD jump-label-issue-946
BUILD data-new
BUILD rela-common-symbols
BUILD gcc-constprop
BUILD special-static
BUILD warn-detect-FAIL
BUILD ppc64le-sibling-call-issue-1003-FAIL
BUILD new-function
TEST gcc-constprop
TEST gcc-constprop-2-issue-935
TEST gcc-static-local-var-5
TEST function-ptr-new
TEST bug-table-section
TEST meminfo-string
TEST gcc-static-local-var-3
TEST ppc64le-bundled-localentry-issue-1007
TEST ASSERT_RTNL-detect
TEST special-static
TEST static-local-size-mismatch-issue-1053
TEST data-read-mostly
TEST fixup-section
TEST mcount_loc-issue-1102
TEST sec-addralign
TEST tracepoints-section
TEST smp-locks-section
TEST data-rel
TEST data-new
TEST rela-common-symbols
TEST new-function

With the preparatory first commit and @gwelymernans 's previous heavy lifting, this removes all of the architecture-specific preprocessor blocks from kpatch-build:

$ grep -c -e '__powerpc64__' -e '__x86_64__' $(git ls-files kpatch-build/) 
kpatch-build/Makefile:0
kpatch-build/create-diff-object.c:0
kpatch-build/create-klp-module.c:0
kpatch-build/create-kpatch-module.c:0
kpatch-build/gcc-plugins/gcc-common.h:0
kpatch-build/gcc-plugins/gcc-generate-rtl-pass.h:0
kpatch-build/gcc-plugins/ppc64le-plugin.c:0
kpatch-build/insn/asm/inat.h:0
kpatch-build/insn/asm/inat_types.h:0
kpatch-build/insn/asm/insn.h:0
kpatch-build/insn/inat-tables.c:0
kpatch-build/insn/inat.c:0
kpatch-build/insn/insn.c:0
kpatch-build/kpatch-build:0
kpatch-build/kpatch-cc:0
kpatch-build/kpatch-elf.c:0
kpatch-build/kpatch-elf.h:0
kpatch-build/kpatch-intermediate.h:0
kpatch-build/kpatch.h:0
kpatch-build/list.h:0
kpatch-build/log.h:0
kpatch-build/lookup.c:0
kpatch-build/lookup.h:0

Leaving as draft for now as there would be a unit-test-objs update required and I also haven't tried it on a ppc64le host yet.

The last part of kpatch_elf_open() calls kpatch_find_func_profiling_calls() to
find and set sym->has_func_profiling.  However, only create-diff-object.c
requires sym->has_func_profiling, so remove the call from
kpatch_elf_open() and let the lone user, create-diff-object, provide and
call it as needed.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
@joe-lawrence
Copy link
Contributor Author

(Rebased against master to fix merge conflict, also tested successfully on ppc64le with make -s unit OBJDIR=objs/x86_64)

@joe-lawrence
Copy link
Contributor Author

bumped the unit-test-objs submodule reference and tweaked the travis file... @sm00th : not sure if you prefer making a change like this, or modify one of the Makefiles (top-level or unit test) to run for both arches.

@sm00th
Copy link
Contributor

sm00th commented Jan 28, 2022

@sm00th : not sure if you prefer making a change like this, or modify one of the Makefiles (top-level or unit test) to run for both arches.

I am starting to think that we might want to remove the arch-specific logic from unit-tests completely now and just run everything every time. But this can come later.

Travis change is ok as a first step (although you also want to update .github/workflows/unit.yml), the problem with this approach is that people running unit tests locally won't run into possible ppc64le issues until they push an MR.

@joe-lawrence
Copy link
Contributor Author

@sm00th : not sure if you prefer making a change like this, or modify one of the Makefiles (top-level or unit test) to run for both arches.

I am starting to think that we might want to remove the arch-specific logic from unit-tests completely now and just run everything every time. But this can come later.

Travis change is ok as a first step (although you also want to update .github/workflows/unit.yml), the problem with this approach is that people running unit tests locally won't run into possible ppc64le issues until they push an MR.

Oh right, I was wondering why I didn't see my update run here in the github PR checks. I can add the change over in unit.yml, but first: if this were to be introduced gradually, does it make sense to implement it for local execution first, then add to gitlab/travis automation? Alternatively, we could take the plunge now and just remove the arch checks from the unit tests.

@sm00th
Copy link
Contributor

sm00th commented Jan 28, 2022

if this were to be introduced gradually, does it make sense to implement it for local execution first, then add to gitlab/travis automation?

I don't see why won't we want it running all the time, ci checks for this repo are not required to pass for us to merge a change so it shouldn't hurt.

Alternatively, we could take the plunge now and just remove the arch checks from the unit tests.

Might be the most straightforward course.

@joe-lawrence joe-lawrence changed the title RFC: Remove host / target architecture assumption from create-diff-object Remove host / target architecture assumption from create-diff-object Jan 28, 2022
@joe-lawrence
Copy link
Contributor Author

Alternatively, we could take the plunge now and just remove the arch checks from the unit tests.

Might be the most straightforward course.

Ok, bombs away. I removed the RFC, so kpatch-build source code style / nits and Makefile gotchas welcome. :)

Copy link
Contributor

@sm00th sm00th left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@joe-lawrence
Copy link
Contributor Author

Fwiw, there is more to do in create-diff-object for making it endian safe. I have some of it already done, but since s390x is not officially supported yet, I'll post as new PRs as I progress/have time.

Copy link
Member

@jpoimboe jpoimboe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice change, I added some style nits, as you requested ;-)

PPC64 = 0x1 << 1,
};

enum architecture target_arch;
Copy link
Member

@jpoimboe jpoimboe Feb 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the global variables could we just make add 'arch' a field of 'kpatch_elf'? Then arch could be set by kpatch_elf_open().

Then ABSOLUTE_RELA_TYPE could be converted to absolute_rela_type(kpatch_elf *kelf) which has a switch statement based on 'kelf.arch', or an ERROR otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this required some plumbing of struct kpatch_elf *kelf through the API, but not too unreasonable.

return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) &&
sym->sym.st_value == 8);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a switch statement here and for all other 'target_arch' checks would help readability and future extensibility instead of if-then-else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I updated all of those sites and also used this opportunity to alphabetize them. (OCD, maybe.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO a switch statement would still help readability here (and be consistent with the other arch checks)

@@ -163,15 +166,13 @@ static int is_bundleable(struct symbol *sym)
*/
static int is_gcc6_localentry_bundled_sym(struct symbol *sym)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While changing this function, it can be converted to bool to more clearly communicate the return semantic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

rela->offset);
} else if (rela->type == R_X86_64_64 ||
rela->type == R_X86_64_32S)
if (target_arch == PPC64)
add_off = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this 'add_off = 0' here is no longer needed since that's now the default initializer at the top of the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up reverting the change to move the initializer to the top. I believe some of the earlier code shuffling invoked a use-but-not-initialized warning from the -O2 build. I no longer hit that warning, and think the add_off = 0 here helps differentiate the two cases (ppc64le vs x86).

.group_size = static_call_sites_group_size,
},
{
.name = ".retpoline_sites",
.arch = X86_64,
.arch = X86_64,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised the compiler didn't complain about this ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eye. That was me telling the compiler I really want it to assign that value.

target_arch = PPC64;
ABSOLUTE_RELA_TYPE = R_PPC64_ADDR64;
break;
default: ERROR("Unsupported target architecture");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A line break between 'default:' and 'ERROR' would help with readability

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@joe-lawrence
Copy link
Contributor Author

Updated for @jpoimboe's review comments. Incremental diff: changes.diff.txt

SOURCES += insn/insn.c insn/inat.c
INSN = insn/insn.o insn/inat.o
insn/%.o: CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
else ifeq ($(ARCH),ppc64le)
ifeq ($(ARCH),ppc64le)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably not a big deal, but believe it or not, there are people out there who cross-compile for x86 on a ppc64le host. Does the plugin not compile on x86?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked at the plugin just yet. The scope of this PR was to only incrementally help create-diff-object so that it may read/write cross-arch ELF for the pre-built unit test objects. AFAIK, the plugin only comes into play for the kernel builds, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense

return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) &&
sym->sym.st_value == 8);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO a switch statement would still help readability here (and be consistent with the other arch checks)

return ((PPC64_LOCAL_ENTRY_OFFSET(sym->sym.st_other) != 0) &&
sym->sym.st_value == 8);
}

return 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return false instead of 0

continue;
#endif
switch(kelf->target_arch) {
case PPC64:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kernel style is to put 'case' on the same indentation level as 'switch', which helps reduce excessive indentation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it? I've observed 50/50 across the kernel, and in fact create-diff-object.c as well :P It looks weird when the last case adds it's own bracketed block like:

switch(foo) {
case 1:
    /* code */
case 99: {
    /* code */
}                          <- appears unbalanced
}

but none of my redundant default cases introduce a local scope, so that never happens here.

Anyway, it's not a big deal, I'll update to help the greater indentation cause.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it? I've observed 50/50 across the kernel

Really? git grep -A1 switch seems to show otherwise.

and in fact create-diff-object.c as well :P

I'm not surprised by that, but it's never too late to change :-)

It looks weird when the last case adds it's own bracketed block like:

switch(foo) {
case 1:
    /* code */
case 99: {
    /* code */
}                          <- appears unbalanced
}

Ew, hopefully we can avoid the need for that.

Anyway, it's not a big deal, I'll update to help the greater indentation cause.

Thanks :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ew, hopefully we can avoid the need for that.

I see now that we did need it. Looks reasonable though :-)

{
if (kelf->target_arch == PPC64) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the 'target_' prefix in 'target_arch' is redundant since the 'kelf' object already represents the target

@joe-lawrence
Copy link
Contributor Author

All review comments implemented, Incremental diff: changes.diff.txt

bwendling and others added 2 commits February 2, 2022 17:36
libelf can read and write various architecture ELF files that may
differ from the host system.  Instead of using preprocessor directives
to build architecture-specific code as per the current host, detect the
intended target architecture from the input ELF files.

Based-on: dynup#1179
Signed-off-by: Bill Wendling <morbo@google.com>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> [small tweaks]
Bump the submodule reference and modify the unit test Makefile to check
all supported architectures.

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
@joe-lawrence
Copy link
Contributor Author

Thanks for the review. One (hopefuly last) update.. it seems like I lost a rela->type assignment along the way in kpatch_create_kpatch_arch_section(), so I added that back in. With that, I'll step back and let our internal integration test bot churn on the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants