This is an archive of the discontinued LLVM Phabricator instance.

[lld] Proposal and example for changing Atom attributes.
AbandonedPublic

Authored by kledzik on Aug 18 2014, 5:50 PM.

Details

Summary

Currently, all the nodes in the Atom graph are read only because "const Atom" is used everywhere. But there are a few cases where it would be nice to make minor modifications to atoms. For example, to implement the darwin linker option -expored_symbols_list, we need to be able to change the scope of atoms. ELF has a case where the dynamicExport attribute on an DefinedAtom may need to
be changed.

There is a couple parts to this patch:

  1. Two new "notify" methods are added to LinkingContext. They are called by the global symbol table when an atom is added to the symbol table.
  1. A setScope() method was added to DefinedAtom. The base implementation just asserts.
  1. For mach-o, yaml, and native the setScope() method modifies the scope of the atom. For the native reader, since the atom is just a pointer into a read-only file buffer, the new scope is stored in a side table.
  1. The darwin driver has support for the -exported_symbols_list option. The MachOLinkingContext notify methods watch for atoms being added to the symbol table with match the symbol names specified by the exported symbols list

and adjust the scope as appropriate.

If the above goes into lld, then for the ELF issue where particular symbols are currently not be added to the .dynsym table, the fix would be to add a new method setDynamicExport(bool) to DefinedAtom, and in ELFLinkingContext implement the "notify" methods to notice the case (DefinedAtom overriding weak shared library atom) and call setDynamicExport(true) on that DefinedAtom.

Diff Detail

Event Timeline

kledzik updated this revision to Diff 12636.Aug 18 2014, 5:50 PM
kledzik retitled this revision from to [lld] Proposal and example for changing Atom attributes..
kledzik updated this object.
kledzik edited the test plan for this revision. (Show Details)
kledzik added a project: lld.
kledzik added a subscriber: Unknown Object (MLST).
ruiu added inline comments.Aug 18 2014, 6:17 PM
include/lld/Core/DefinedAtom.h
233

I assume we will add more setXX member functions (e.g. setInterposable) when we need it. I don't like to add them now but want to make sure that we are on the same page.

include/lld/Core/LinkingContext.h
230

This function signature made me a bit sad because it's intended to mutate a given atom despite it takes const Atom *. We may probably want to make the atom graph mutable in the first place, because it's no longer actually const because of the addition of this function, so that we don't have to sprinkle const_casts in many places. I don't like to see that change in this CL but it may need to be considered later.

239

I like this function. I'll use it for PE/COFF as well -- when an undefined atom specified by "--undefined" (or "/include" on Windows) is coalesced with a defined atom, I want to copy that atom's deadStrip attribute to a new atom.

lib/Core/DefinedAtom.cpp
87

Does this have to be compared with the current value? I don't think we want to call setScope() if it's not really implemented. It seems to me that we can just put llvm_unreachable here.

lib/ReaderWriter/MachO/MachOLinkingContext.cpp
585

You can early return here if you invert the condition inside if.

602

if (currentlyGlobal && currentlyGlobal == blacklisted)?

kledzik added inline comments.Aug 18 2014, 6:55 PM
include/lld/Core/DefinedAtom.h
233

Yes. I alluded to that in the overview, that the ELF could add setExportDynamic()

include/lld/Core/LinkingContext.h
230

Yes. For now the graph is 99.9% const, so a few const_cast<> keeps it closer to what we are trying to model. But if we have Passes that need to modify atoms, or lots of places need start modifying atoms, it will probably make sense to remove the const in the zillion places.

lib/Core/DefinedAtom.cpp
87

I started with that, but thought it would be odd to case an abort if something called setScope() and was not actually changing the scope. I'll change it back.

lib/ReaderWriter/MachO/MachOLinkingContext.cpp
585

yes!

602

It reduces to:

if (currentlyGlobal && blacklisted)
shankarke requested changes to this revision.Aug 18 2014, 7:36 PM
shankarke edited edge metadata.
shankarke added inline comments.
include/lld/Core/LinkingContext.h
230

Various flavors can go over the atoms in pass and set the appropriate attributes right, Am I missing something ? Same with the below function as well.

lib/Core/DefinedAtom.cpp
86

I think visibility and scope are being mixed. While scope needs to be a property of the atom, I am not convinced visibility has to be part of the Atom has well, as visibility is mostly user driven.

lib/ReaderWriter/MachO/MachOLinkingContext.cpp
588

Arent we mixing visibility and scope here ? I think its better to add visibility as a separate attribute.

lib/ReaderWriter/Native/ReaderNative.cpp
888–894

Is this needed anytime ? What kind of usecase is this ?

This revision now requires changes to proceed.Aug 18 2014, 7:36 PM
atanasyan edited edge metadata.Aug 19 2014, 1:29 AM

Due time zone difference I just to add my two cents - I like the the target independent part of this patch and agree with Rui that we need to make the atom graph mutable in a separate patch before or after this one. The atom graph will never be immutable from now and we should not hide this fact.

kledzik added inline comments.Aug 19 2014, 12:08 PM
include/lld/Core/LinkingContext.h
230

Shankar, Passes are run after resolving is done. So a Pass cannot tell, for instance, that a DefineAtom replaced a weak SharedLibraryAtom (which for ELF means the DefinedAtom should be dynamicExport). These hooks give the flavor's LinkingContext a change to record such flavor specific info.

lib/Core/DefinedAtom.cpp
86

What do you mean by "visibility"? The lld model does not have a visibility concept.

The ELF file format started with just two levels of scope (STB_LOCAL and STB_GLOBAL). Later the middle level of scope (linkage unit) was invented, for ELF it is represented as STB_GLOBAL plus STV_HIDDEN on the side.

lib/ReaderWriter/Native/ReaderNative.cpp
888–894

This is to show that we can add setters to the NativeReader even though the native file is mapped read-only. In the future if a flavor needs to use setters and someone stores a input file in native, we need the setters to work.

kledzik abandoned this revision.Aug 20 2014, 1:56 PM