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

[llvm-readobj] Fixes malformed json on JSON printed corefiles #92835

Merged

Conversation

feg208
Copy link
Contributor

@feg208 feg208 commented May 20, 2024

This patch fixes an issue where, when printing corefile notes with llvm-readobj as json, the dumper generated llvm formatted output which isn't valid json. This alters the dumper to, in the NT_FILE, note, dump properly formatted json data.

Prior to this patch the JSON output was formatted like:

               "Mapping": [
                 "Start": 4096,
                 "End": 8192,
                 "Offset": 12288,
                 "Filename": "/path/to/a.out"
               ],

Whereas now it is formatted as:

              "Mappings": [
                {
                  "Start": 4096,
                  "End": 8192,
                  "Offset": 12288,
                  "Filename": "/path/to/a.out"
                },

Which is valid. Additionally the LLVM output has changed to match the structure of the JSON output (i.e. instead of lists of keys it is a list of dictionaries)

@llvmbot
Copy link
Collaborator

llvmbot commented May 20, 2024

@llvm/pr-subscribers-llvm-binary-utilities

Author: Fred Grim (feg208)

Changes

This patch fixes an issue where, when printing corefile notes with llvm-readobj as json, the dumper generated llvm formatted output which isn't valid json. This alters the dumper to, in the NT_FILE, note use a JSON particular method and dump properly formatted json data.


Full diff: https://github.com/llvm/llvm-project/pull/92835.diff

2 Files Affected:

  • (modified) llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test (+38)
  • (modified) llvm/tools/llvm-readobj/ELFDumper.cpp (+27-12)
diff --git a/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test b/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
index 752cb723cd221..dab539821f6de 100644
--- a/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
+++ b/llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
@@ -3,6 +3,8 @@
 # RUN: yaml2obj %s -o %t.o
 # RUN: llvm-readelf --notes %t.o | FileCheck %s --check-prefix=GNU
 # RUN: llvm-readobj --notes %t.o | FileCheck %s --check-prefix=LLVM
+# RUN: llvm-readelf --elf-output-style=JSON --pretty-print --notes %t.o | FileCheck %s --check-prefix=JSON
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print --notes %t.o | FileCheck %s --check-prefix=JSON
 
 ## llvm-mc doesn't support generating ET_CORE files; the 'Content' field was
 ## generated with the following steps:
@@ -93,3 +95,39 @@ ProgramHeaders:
 # LLVM-NEXT:     }
 # LLVM-NEXT:   }
 # LLVM-NEXT: ]
+
+# JSON:      "Notes": [
+# JSON-NEXT:  {
+# JSON-NEXT:      "NoteSection": {
+# JSON-NEXT:          "Name": "<?>",
+# JSON-NEXT:          "Offset": 120,
+# JSON-NEXT:          "Size": 148,
+# JSON-NEXT:          "Note": {
+# JSON-NEXT:              "Owner": "CORE",
+# JSON-NEXT:              "Data size": 128,
+# JSON-NEXT:              "Type": "NT_FILE (mapped files)",
+# JSON-NEXT:              "Page Size": 4096,
+# JSON-NEXT:              "Mappings": [
+# JSON-NEXT:                {
+# JSON-NEXT:                  "Start": 4096,
+# JSON-NEXT:                  "End": 8192,
+# JSON-NEXT:                  "Offset": 12288,
+# JSON-NEXT:                  "Filename": "/path/to/a.out"
+# JSON-NEXT:                },
+# JSON-NEXT:                {
+# JSON-NEXT:                  "Start": 16384,
+# JSON-NEXT:                  "End": 20480,
+# JSON-NEXT:                  "Offset": 24576,
+# JSON-NEXT:                  "Filename": "/path/to/libc.so"
+# JSON-NEXT:                },
+# JSON-NEXT:                {
+# JSON-NEXT:                  "Start": 28672,
+# JSON-NEXT:                  "End": 32768,
+# JSON-NEXT:                  "Offset": 36864,
+# JSON-NEXT:                  "Filename": "[stack]"
+# JSON-NEXT:                }
+# JSON-NEXT:            ]
+# JSON-NEXT:          }
+# JSON-NEXT:      }
+# JSON-NEXT: }
+# JSON-NEXT: ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index a752cc4015293..4558dcdf62bfe 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -180,6 +180,16 @@ struct GroupSection {
   std::vector<GroupMember> Members;
 };
 
+struct CoreFileMapping {
+  uint64_t Start, End, Offset;
+  StringRef Filename;
+};
+
+struct CoreNote {
+  uint64_t PageSize;
+  std::vector<CoreFileMapping> Mappings;
+};
+
 namespace {
 
 struct NoteType {
@@ -762,6 +772,7 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
                                           const unsigned SecNdx);
   virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const;
   virtual void printEmptyGroupMessage() const;
+  virtual void printCoreNote(const CoreNote &Note, ScopedPrinter &W) const;
 
   ScopedPrinter &W;
 };
@@ -793,6 +804,8 @@ template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {
 
   void printEmptyGroupMessage() const override;
 
+  void printCoreNote(const CoreNote &Note, ScopedPrinter &W) const override;
+
 private:
   std::unique_ptr<DictScope> FileScope;
 };
@@ -5736,16 +5749,6 @@ static AMDGPUNote getAMDGPUNote(uint32_t NoteType, ArrayRef<uint8_t> Desc) {
   }
 }
 
-struct CoreFileMapping {
-  uint64_t Start, End, Offset;
-  StringRef Filename;
-};
-
-struct CoreNote {
-  uint64_t PageSize;
-  std::vector<CoreFileMapping> Mappings;
-};
-
 static Expected<CoreNote> readCoreNote(DataExtractor Desc) {
   // Expected format of the NT_FILE note description:
   // 1. # of file mappings (call it N)
@@ -7838,7 +7841,7 @@ static bool printLLVMOMPOFFLOADNoteLLVMStyle(uint32_t NoteType,
   return true;
 }
 
-static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
+template <class ELFT> void LLVMELFDumper<ELFT>::printCoreNote(const CoreNote &Note, ScopedPrinter &W) const {
   W.printNumber("Page Size", Note.PageSize);
   for (const CoreFileMapping &Mapping : Note.Mappings) {
     ListScope D(W, "Mapping");
@@ -7849,6 +7852,18 @@ static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
   }
 }
 
+template <class ELFT> void JSONELFDumper<ELFT>::printCoreNote(const CoreNote &Note, ScopedPrinter &W) const {
+  W.printNumber("Page Size", Note.PageSize);
+  ListScope D(W, "Mappings");
+  for (const CoreFileMapping &Mapping : Note.Mappings) {
+    auto MappingDict = std::make_unique<DictScope>(W);
+    W.printHex("Start", Mapping.Start);
+    W.printHex("End", Mapping.End);
+    W.printHex("Offset", Mapping.Offset);
+    W.printString("Filename", Mapping.Filename);
+  }
+}
+
 template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
   ListScope L(W, "Notes");
 
@@ -7916,7 +7931,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
             Descriptor, ELFT::Endianness == llvm::endianness::little,
             sizeof(Elf_Addr));
         if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {
-          printCoreNoteLLVMStyle(*N, W);
+          printCoreNote(*N, W);
           return Error::success();
         } else {
           return N.takeError();

Copy link

github-actions bot commented May 20, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch 2 times, most recently from b13bd03 to cd2bbc5 Compare May 20, 2024 23:19
@feg208 feg208 requested a review from lattner May 20, 2024 23:49
@lattner lattner removed their request for review May 21, 2024 00:13
Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

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

Rather than adding a near-duplicate method to work around the fact that the existing code doesn't do what we need it to for JSON output, could we instead simply change the existing code to produce output that is valid (i.e. replace the existing function with the new one you've written)? It would mean that the LLVM output would change, but I don't think this is an issue: as far as I'm aware, we don't promise full output compatibility between LLVM releases of the LLVM-style output. We'd want a release note in this case, to advise of both the JSON fix and the change in LLVM style.

llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test Outdated Show resolved Hide resolved
@feg208
Copy link
Contributor Author

feg208 commented May 21, 2024

It would mean that the LLVM output would change, but I don't think this is an issue: as far as I'm aware, we don't promise full output compatibility between LLVM releases of the LLVM-style output. We'd want a release note in this case, to advise of both the JSON fix and the change in LLVM style.

Sure. As long as that is ok. I didn't really know what the expectation for the llvm format was.

@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch from cd2bbc5 to 1092775 Compare May 21, 2024 14:24
@feg208
Copy link
Contributor Author

feg208 commented May 21, 2024

@jh7370 I made the recommended changes and updated the llvm style test

@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch 2 times, most recently from 96123b6 to 0d2ce21 Compare May 21, 2024 16:19
Copy link
Contributor

@ilovepi ilovepi left a comment

Choose a reason for hiding this comment

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

This looks good from my perspective. and I agree w/ @jh7370 about the compatibility and approach. Please do wait for his LGTM before landing, though.

Can you also include an example of the bad vs. corrected JSON in the commit message? Something minimal to show what's changed is probably fine.

@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch from 0d2ce21 to dcf3084 Compare May 21, 2024 16:57
@feg208
Copy link
Contributor Author

feg208 commented May 21, 2024

Can you also include an example of the bad vs. corrected JSON in the commit message? Something minimal to show what's changed is probably fine.

Done!

@ilovepi
Copy link
Contributor

ilovepi commented May 21, 2024

Totally up to you, but I'd just show the relevant bits.

"Mapping": [
     "Start": 4096,
     "End": 8192,
     "Offset": 12288,
     "Filename": "/path/to/a.out"
],
"Mappings": [
  {
     "Start": 4096,
     "End": 8192,
     "Offset": 12288,
     "Filename": "/path/to/a.out"
  },
 ...
]

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

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

Code looks good, barring a doc issue. Please also update the PR description to match the current change, in particular noting that the LLVM output has been structurally changed to make it work for JSON output too.

@@ -238,6 +238,10 @@ Changes to the LLVM tools
documented in `--help` output and the command guide. (`#90474
<https://github.com/llvm/llvm-project/pull/90474>`)

* llvm-readobj's LLVM output has changed format for ELF core files. The
NT_FILE note now has a map for the mapped files
(`https://github.com/llvm/llvm-project/pull/92835`_).
Copy link
Collaborator

Choose a reason for hiding this comment

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

Something about this text is causing the pre-merge check for the doc build to fail. I think it's because you've not included a short-hand for the link (e.g. like the #90474 in the example above).

@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch from dcf3084 to 38e8187 Compare May 22, 2024 15:39
@feg208
Copy link
Contributor Author

feg208 commented May 22, 2024

Code looks good, barring a doc issue. Please also update the PR description to match the current change, in particular noting that the LLVM output has been structurally changed to make it work for JSON output too.

@jh7370 I altered the documentation and shortened the commit message along the lines laid out in @ilovepi's comments

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

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

In the PR description:

NT_FILE, note use

I think "note" here should be "now".

LGTM, with that and the other inline comment.

llvm/docs/ReleaseNotes.rst Outdated Show resolved Hide resolved
This patch fixes an issue where, when printing corefile notes with
llvm-readobj as json, the dumper generated llvm formatted output
which isn't valid json. This alters the dumper to, in the NT_FILE,
note use a JSON particular method and dump properly formatted json
data.
Prior to this patch the JSON output was formatted like:
```

    "Mapping": [
        "Start": 4096,
        "End": 8192,
        "Offset": 12288,
        "Filename": "/path/to/a.out"
    ],
    ...
```
Whereas now it is formatted as:
```

    "Mappings": [
        {
            "Start": 4096,
            "End": 8192,
            "Offset": 12288,
            "Filename": "/path/to/a.out"
        },
        ...
```
Which is valid.
@feg208 feg208 force-pushed the users/feg208/fixes_malformed_json_in_llvm_readobj branch from 38e8187 to 5e254df Compare May 23, 2024 15:51
@feg208 feg208 merged commit 942a6af into llvm:main May 23, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants