[llvm] [llvm-objdump] Print out xcoff file header for xcoff object file with option private-headers (PR #96350)

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 14 00:39:11 PDT 2024


================
@@ -30,10 +32,86 @@ using namespace llvm::support;
 
 namespace {
 class XCOFFDumper : public objdump::Dumper {
+  const XCOFFObjectFile &Obj;
+  unsigned Width;
+
 public:
-  XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
-  void printPrivateHeaders() override {}
+  XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O), Obj(O) {}
+
+private:
+  void printPrivateHeaders() override;
+  void printFileHeader();
+  FormattedString formatName(StringRef Name);
+  void printHex(StringRef Name, uint64_t Value);
+  void printNumber(StringRef Name, uint64_t Value);
+  void printStrHex(StringRef Name, StringRef Str, uint64_t Value);
+  void setWidth(unsigned W) { Width = W; };
 };
+
+void XCOFFDumper::printPrivateHeaders() { printFileHeader(); }
+
+FormattedString XCOFFDumper::formatName(StringRef Name) {
+  return FormattedString(Name, Width, FormattedString::JustifyLeft);
+}
+
+void XCOFFDumper::printHex(StringRef Name, uint64_t Value) {
+  outs() << formatName(Name) << format_hex(Value, 0) << "\n";
+}
+
+void XCOFFDumper::printNumber(StringRef Name, uint64_t Value) {
+  outs() << formatName(Name) << format_decimal(Value, 0) << "\n";
+}
+
+void XCOFFDumper::printStrHex(StringRef Name, StringRef Str, uint64_t Value) {
+  outs() << formatName(Name) << Str << " (" << format_decimal(Value, 0)
+         << ")\n";
+}
+
+void XCOFFDumper::printFileHeader() {
+  setWidth(20);
+  outs() << "\n---File Header:\n";
+  printHex("Magic:", Obj.getMagic());
+  printNumber("NumberOfSections:", Obj.getNumberOfSections());
+
+  int32_t TimeStamp = Obj.getTimeStamp();
+  if (TimeStamp > 0) {
+    // This handling of the timestamp assumes that the host system's time_t is
+    // compatible with AIX time_t. If a platform is not compatible, the lit
+    // tests will let us know.
+    time_t TimeDate = TimeStamp;
+
+    char FormattedTime[80] = {};
+
+    size_t BytesFormatted = std::strftime(FormattedTime, sizeof(FormattedTime),
+                                          "%F %T", gmtime(&TimeDate));
----------------
jh7370 wrote:

`gmtime` needs the `std::` prefix.

80 characters is way too many. Assuming 4 digit years (good for nearly 8000 years ;) ), this string will be a total of 20 characters, including the null terminator. If you're actually concerned the size might not be enough, you can instead use a resizeable buffer like `std::vector`, check the result and repeat with a bigger buffer size, if needed, like the following example (warning, I haven't tested the below, but the approach should be clear):

```
std::tm *CalenderTime = std::gmtime(&TimeDate);
std::vector<char> FormattedTime(20);
while (true) {
  size_t BytesFormatted = std::strftime(FormattedTime, FormattedTime.size(), "%F %T", CalendarTime);
  if (BytesFormatted)
    break;
  BytesFormatted.resize(BytesFormatted.size() * 2);
}
printStrHex("Timestamp:", FormattedTime.data(), TimeStamp);
```

https://github.com/llvm/llvm-project/pull/96350


More information about the llvm-commits mailing list