Skip to content

Fix reading metadata from ELF sections #33321

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

Merged
merged 1 commit into from
Aug 12, 2020

Conversation

augusto2112
Copy link
Contributor

@augusto2112 augusto2112 commented Aug 5, 2020

This PR fixes reading in the ELF sections related to metadata. Since the Section Table Header and String Table are not present in the process, we read them from the executable's file instead. We then read the relevant sections from the offset given by the Section Table Header in the process's address space.

@adrian-prantl @vedantk

Copy link
Contributor Author

@augusto2112 augusto2112 left a comment

Choose a reason for hiding this comment

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

The relevant sections are read from the child process inside fieldELFSectionByName, the code there is unchanged:

    auto findELFSectionByName = [&](std::string Name)
        -> std::pair<RemoteRef<void>, uint64_t> {
      // Now for all the sections, find their name.
      for (const typename T::Section *Hdr : SecHdrVec) {
        uint32_t Offset = Hdr->sh_name;
        auto SecName = std::string(StrTab + Offset);
        if (SecName != Name)
          continue;
        auto SecStart =
            RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr);
        auto SecSize = Hdr->sh_size;
        auto SecBuf = this->getReader().readBytes(SecStart, SecSize);
        auto SecContents = RemoteRef<void>(SecStart.getAddressData(),
                                           SecBuf.get());
        savedBuffers.push_back(std::move(SecBuf));
        return {SecContents, SecSize};
      }
      return {nullptr, 0};
    };

@augusto2112 augusto2112 changed the title WIP - Fix reading from elf sections Fix reading metadata from ELF sections Aug 6, 2020
@augusto2112
Copy link
Contributor Author

@mikeash @jckarter @compnerd Could you take a look, please? (I can't request reviews the normal way since I don't have write access).

@jckarter
Copy link
Contributor

jckarter commented Aug 6, 2020

How do we get access to the file? There might not be one if the target is a running process.

@adrian-prantl
Copy link
Contributor

How do we get access to the file? There might not be one if the target is a running process.

It's a good point to raise that we need to gracefully handle the case where the buffer is empty. For the debugger use-case LLDB knows how find the file for a process.

@augusto2112
Copy link
Contributor Author

How do we get access to the file? There might not be one if the target is a running process.

@jckarter Right now, using the ObjectFile API in LLDB, see: swiftlang/llvm-project#1608

I think that if we'd like to do this using only the running process, we'd need to undo the stripping of Section Table Header and mark shstrtab as alloc.

@jckarter
Copy link
Contributor

jckarter commented Aug 6, 2020

If that's a possibility, mapping the section table header sounds like an interesting thing to try, since it would allow ELF handling to behave more like Mach-O and PE handling on Mac/Windows, and let us avoid bugs/exploits where the binary on disk drifts from what was originally mapped into memory.

@augusto2112
Copy link
Contributor Author

@jckarter I just talked with @compnerd. Unfortunately, there's no way we can guarantee the Section Header Table is present in the running process, as it's removed by the stripper and we have no control over it :(

@adrian-prantl
Copy link
Contributor

I think we're almost there!

Copy link
Contributor

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

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

Thank you!

@adrian-prantl
Copy link
Contributor

@swift-ci smoke test

@augusto2112
Copy link
Contributor Author

@adrian-prantl thanks for iterating on this with me so quickly!

@adrian-prantl
Copy link
Contributor

@swift-ci smoke test

@augusto2112
Copy link
Contributor Author

@adrian-prantl It looks like some tests depended on the old readELF. I have no idea how that'd work, since even if the section header and string header were present, the old implementation had a bug where it'd read some data that was already freed... I'll debug the tests here to understand how they were passing when reading only from the process.

@augusto2112 augusto2112 force-pushed the read-elf-sections branch 3 times, most recently from be187ab to 628529b Compare August 11, 2020 21:09
@augusto2112
Copy link
Contributor Author

@adrian-prantl We actually need to keep readELF working with only the image start. This is used when the MemoryReader instance reads from a file (in the failing tests, swift-reflection-dump's ObjectMemoryReader).

I've updated the PR to read from the buffer if it's present, otherwise read using the MemoryReader. I've also made sure we read everything from the buffer if it's available.

@adrian-prantl
Copy link
Contributor

@swift-ci smoke test

1 similar comment
@adrian-prantl
Copy link
Contributor

@swift-ci smoke test

@adrian-prantl adrian-prantl merged commit f86b951 into swiftlang:master Aug 12, 2020
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.

3 participants