Support for multiple source files#1204
Conversation
| continue; | ||
|
|
||
| if (sym->type == STT_FILE) | ||
| break; |
There was a problem hiding this comment.
I'm not quite convinced this won't cause a regression. It's possible to have multiple STT_FILE symbols with the same name. How can we be sure this is the right file? For example, issue #604.
There was a problem hiding this comment.
I guessed that shouldn't be that easy but failed to find this case. Pushed v2 that does locals_match() for every STT_FILE section in the file and stores lookup_table->local_syms in each symbol.
kpatch-build/create-diff-object.c
Outdated
| if (sym1->lookup_table_sym && !sym2->lookup_table_sym) | ||
| sym2->lookup_table_sym = sym1->lookup_table_sym; | ||
| else if (!sym1->lookup_table_sym && sym2->lookup_table_sym) | ||
| sym1->lookup_table_sym = sym2->lookup_table_sym; |
There was a problem hiding this comment.
I think the else case isn't really needed since 'sym1' is always from the orig object and 'sym2' is always from the patched object. If that's not clear then maybe they need to be renamed to orig_sym and patched_sym.
There was a problem hiding this comment.
Yes, all current usage of kpatch_correlate_symbol() follows this logic, I was safeguarding against possible future code, but maybe making expectations clear through argument names will be enough.
kpatch-build/lookup.c
Outdated
| for (child = child_locals; child->name; child++) { | ||
| if (child->type == sym->type && | ||
| !strcmp(child->name, sym->name)) { | ||
| iter_sym = file_sym; |
There was a problem hiding this comment.
The variable names were already fairly confusing in this function, but the addition of struct symbol to this file confuses the naming even more. There's no logical difference between sym and iter_sym when reading the code.
I'd suggest making the following naming changes here, as well as in other places with struct object_symbol *sym.
- rename
symtotable_sym. - rename
iter_symtosym.
That way, sym has its traditional meaning (an instance of struct symbol *) and table_sym is more appropriately named.
There was a problem hiding this comment.
Thanks, good suggestion. I was struggling with variable naming in this patchset, at some point I had lookup_sym->lookup_sym in lookup_local_symbol().
| break; | ||
| if (iter_sym->bind != STB_LOCAL) | ||
| continue; | ||
|
|
There was a problem hiding this comment.
To match the previous functionality I think we also want to make sure it's either an STT_FUNC or an STT_OBJECT (and otherwise continue).
There was a problem hiding this comment.
This is actually intentional, so is the removal in the next comment. The very next statement is iter_sym->type == sym->type which does make sure the type is one of those possibilities so the check was redundant. Or do you think it is worth keeping it for clarity?
| if (sym->bind != STB_LOCAL) | ||
| continue; | ||
| if (sym->type != STT_FUNC && sym->type != STT_OBJECT) | ||
| continue; |
There was a problem hiding this comment.
If my above suggestion to check for STT_{FUNC,OBJECT} is taken, this hunk probably doesn't need removed.
kpatch-build/lookup.c
Outdated
| } | ||
| } | ||
|
|
||
| static void link_local_symbols(struct lookup_table *table, struct kpatch_elf *kelf) |
There was a problem hiding this comment.
link_local_symbols() makes it sound like something different than finding, when in fact it's just a loop around find_local_syms(). Maybe call it find_local_syms_multiple() or so? Also I think this function deserves a comment describing why it's doing this. I assume it's for analyzing a bigger .o file like a built-in.o or vmlinux.o.
Similarly, the commit message needs more detail, as "support object-files built from multiple sources" didn't make sense to me until after I studied the code. The commit message should also give more info about what problem is being solved and why.
kpatch-build/kpatch-elf.h
Outdated
| struct section *sec; | ||
| GElf_Sym sym; | ||
| char *name; | ||
| struct object_symbol *lookup_table_sym; |
There was a problem hiding this comment.
Technically this should probably be called lookup_table_file_sym, since it points to the lookup table's FILE symbol rather than the corresponding symbol itself.
That said, maybe it would be simpler to just set it to the exact corresponding symbol to begin with. locals_match() already finds the corresponding symbol -- twice, in fact. Then, later, lookup_local_symbol() finds it a third time. Can we just set sym->lookup_table_sym to the corresponding symbol to begin with, in find_local_syms() and/or locals_match()? Then lookup_local_symbol() becomes redundant.
There was a problem hiding this comment.
Ah, I see. That makes sense, I'll see if it will work.
There was a problem hiding this comment.
After looking into this I currently don't see a straightforward way of dropping lookup_local_symbol(). The only reason is sympos calculation it does. Because of that we'll either have to traverse the whole lookup table for each symbol in find_local_syms() (which will make things worse) or keep a list of seen symbol names and write down sympos in symtab_read() but I am not sure it is worth doing that. Any thoughts? Can we leave it as is for now?
There was a problem hiding this comment.
That's fine. In that case my only comment here would be to rename 'lookup_table_sym' to 'lookup_table_file_sym'.
kpatch-build/lookup.c
Outdated
| @@ -92,9 +91,9 @@ static int maybe_discarded_sym(const char *name) | |||
| } | |||
|
|
|||
| static int locals_match(struct lookup_table *table, int idx, | |||
There was a problem hiding this comment.
While you're at it, can you change locals_match() and maybe_discarded_sym() to return bool? Their int return codes are opposite than normal kernel error code expectations, making them extra confusing. Might as well clean those up while we're touching the code.
77371fd to
e1bd041
Compare
jpoimboe
left a comment
There was a problem hiding this comment.
Would it be possible to add a unit test? vmlinux.o is probably too big, but either a built-in.o file or some manually linked version of multiple .o's might be useful.
kpatch-build/create-diff-object.c
Outdated
| struct section *sec_patched) | ||
| { | ||
| CORRELATE_ELEMENT(sec1, sec2, "section"); | ||
| CORRELATE_ELEMENT(sec_base, sec_patched, "section"); |
There was a problem hiding this comment.
This is a nice cleanup IMO. The new naming helps to codify certain existing assumptions.
While making such a broad change, I'd suggest one more naming tweak (but arguments to the contrary are welcome). I've long regretted the use of the term "base" in this code. I'd argue that "orig" is more descriptive than "base" (and matches the directory names in ~/.kpatch/tmp/.) Since you're already doing a mass renaming which adds more "base", I'd suggest going ahead and doing s/base/orig/g pretty much everywhere -- if there are no objections.
And sorry about pulling this PR into the weeds :-)
|
v3: base->orig rename. I've also created dynup/kpatch-unit-test-objs#34 that will be added to this PR once merged. |
|
Looks good to me. |
gcc-static-local-var-4.patch is disabled on this distribution, disable the test as well as it will always fail during 'slow' integration test runs. Signed-off-by: Artem Savkov <asavkov@redhat.com>
At the moment lookup_symbol() takes symbol name as an argument which might not be enough in some cases (e.g. for objectfiles built from multiple source files). Make it accept full symbol structure. Signed-off-by: Artem Savkov <asavkov@redhat.com>
So far create-diff-object worked only with objectfiles built from a single source file. To support object-files built from multiple sources such as linked vmlinux.o, we call locals_match() for each of STT_FILE symbols and store the pointer to the beginning of appropriate symbol block in lookup table in each symbol. Signed-off-by: Artem Savkov <asavkov@redhat.com>
…urn bool Change the return type of locals_match() and maybe_discarded_sym() to better reflect their usage. Signed-off-by: Artem Savkov <asavkov@redhat.com>
Rename "base" to "orig" when referencing object files and their contents to be consistent with temporary directory structure. Signed-off-by: Artem Savkov <asavkov@redhat.com>
While theoretically most of these functions can work both ways right now all calls follow the same pattern: first argument is orig element and second is patched element. Rename the arguments so that these functions are used in the same fashion going forward. This allows us to cut some corners such as removing the elseif statement in kpatch_correlate_symbol(). Signed-off-by: Artem Savkov <asavkov@redhat.com>
Update unit-test submodule pointer to include a multi-file unit-test. Signed-off-by: Artem Savkov <asavkov@redhat.com>
|
v3: included unit-tests and rebased on top of #1207 |
This will eventually help support kernel-LTO, right? The code looks good to me, including all the cleanups. (Btw, if you think this PR is ready for merge, ok, if not ... would it be easier to spin off the integration test and cleanup commits to make future rebases easier?) |
Right, with LTO we won't have the luxury to work with individual objectfiles.
No, not to my knowledge at least. This series doesn't make single source file case any worse, just makes create-diff-object more flexible.
From the test-objs commit message: So this is not exactly a real-life scenario.
Do you expect ppc64le elfs to have something special about them in this case? If not I don't see any reason to add them since they will be running through the same code. I think we should focus mostly on x86_64 since they are ran more frequently (travis/github runs only on x86_64) and only add ppc64le ones when that case is different.
It is ready, just wanted to give you a chance to take a look. Will merge it now and we can add unit tests later if it comes to that. |
This patchset allows create-diff-object to work on objectfiles built from multiple source files.