[PATCH] D120357: [llvm-nm]add helper function to print out the object file name, archive name, architecture name
Digger Lin via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 2 07:22:28 PST 2022
DiggerLin added inline comments.
================
Comment at: llvm/test/Object/nm-universal-binary.test:38
-CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
+CHECK-AR: {{[[:space:]].*}}macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
CHECK-AR: 0000000000000068 s EH_frame0
----------------
jhenderson wrote:
> Adding `{{[[:space:]].*}}` does literally nothing useful, as the whitespace at the start of a line is ignored unless using both `--strict-whitespace` and `--match-full-lines` in the FileCheck command. I believe, if you want to check the first line is empty, that you can use:
>
> ```
> CHECK-AR: {{^$}}
> CHECK-AR-NEXT: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
> ```
>
> For later blank lines, you can do `CHECK-EMPTY:` immediately following a regular `CHECK`. `CHECK-EMPTY` works like `CHECK-NEXT` but ensures the line is completely blank instead of checking against some pattern. Since it works like `CHECK-NEXT` it cannot be used as the first `CHECK` pattern however. Conversely, `{{^$}}` will not always work if used after the first `CHECK` pattern. This is because FileCheck consumes the string it has matched up to before running the next `CHECK`. For example, imagine the output was:
> ```
> foo
> bar
> ```
> And we have the following CHECKs:
> ```
> CHECK: foo
> CHECK-NEXT: {{^$}}
> CHECK-NEXT: bar
> ```
> to test that there is a blank line between foo and bar. In this case, after matching `foo`, the output will look like a blank line, followed by a line containing bar. The attempt to check for an empty line matches the first line (at the end of foo), which is not the line after the previous match, so the CHECK-NEXT fails.
>
> (Aside, not something for you to fix, but this test is full of holes, and could fail to catch symbols in the output that shouldn't be present, or other additional lines).
thanks a lot for your detail explanation.
================
Comment at: llvm/tools/llvm-nm/llvm-nm.cpp:1889
+ CurrentFilename = Obj.getFileName();
+ if (IsSymbolsEmpty && SymbolList.empty() && !Quiet) {
writeFileName(errs(), ArchiveName, ArchitectureName);
----------------
jhenderson wrote:
> DiggerLin wrote:
> > jhenderson wrote:
> > > Why have you just introduced this change? How is it better than the previous code?
> > yes, in the original code of function getSymbolNamesFromObject( )
> >
> > ```
> > auto Symbols = Obj.symbols();
> > .....
> >
> > if (DynamicSyms) {
> > const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
> > if (!E) {
> > error("File format has no dynamic symbol table", Obj.getFileName());
> > return;
> > }
> > Symbols = E->getDynamicSymbolIterators();
> > ```
> > The value of Symbols be changed by the line
> > Symbols = E->getDynamicSymbolIterators();
> > Symbols maybe not the equal to Obj.symbols()
> >
> > so we can not use the
> > if ( Obj.symbols().empty() && SymbolList.empty() && !Quiet)
> Thanks, I see. I think I'd prefer it if you pulled the logic on whether or not an object has symbols into a separate function (maybe `hasSymbols`) which takes `Obj` and returns the value based on the appropriate set of symbols for whether `DynamicSyms` is specified or not. You probably would then benefit from a separate helper function used by this new function and `getSymbolNamesFromObject` that returns the dynamic symbols list (or an empty list if there was an error). Something like the following:
>
> ```
> static bool hasSymbols(SymbolicFile &Obj) {
> if (DynamicSyms)
> return !getDynamicSyms(Obj).empty();
> return !Obj.symbols().empty();
> }
>
> static <insert return type here> getDynamicSyms(SymbolFile &Obj) {
> const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
> if (!E) {
> error("File format has no dynamic symbol table", Obj.getFileName());
> return {};
> }
> return E->getDynamicSymbolIterators();
> }
> ```
as your suggestion, the function getDynamicSyms() will be call twice .
1. One is in the function
getSymbolNamesFromObject
2 . the other is in hasSymbols() which will be called in the function
dumpSymbolNamesFromObject()
if there is error.
> if (!E) {
> error("File format has no dynamic symbol table", Obj.getFileName());
> return {};
> }
the error info will be print out twice.
if I keep the code in the
as
```
static bool getSymbolNamesFromObject(SymbolicFile &Obj, bool &IsSymbolsEmpty) {
auto Symbols = Obj.symbols();
std::vector<VersionEntry> SymbolVersions;
if (DynamicSyms) {
const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
if (!E) {
error("File format has no dynamic symbol table", Obj.getFileName());
return false;
}
Symbols = E->getDynamicSymbolIterators();
```
there is no advantage of adding a two helper function.
I do not think adding a new parameter "bool &IsSymbolsEmpty" is a big problem.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D120357/new/
https://reviews.llvm.org/D120357
More information about the llvm-commits
mailing list