This is an archive of the discontinued LLVM Phabricator instance.

Linking of shared libraries for MIPS little-endian 32-bit target
AbandonedPublic

Authored by atanasyan on Nov 12 2013, 1:14 PM.

Details

Summary

The patch implements linking of shared libraries for MIPS little-endian 32-bit target. Now supported a limited set of relocations and linking is possible in trivial cases only.

The following are the most significant peculiarities of MIPS target:

  • MIPS ABI requires some special tags in the dynamic table.
  • GOT consists of two parts local and global. The local part contains entries refer locally visible symbols. The global part contains entries refer global symbols.
  • Entries in the .dynsym section which have corresponded entries in the GOT should be:
    1. Emitted at the end of .dynsym section
    2. Sorted accordingly to theirs GOT counterparts
  • There are “paired” relocations. One or more R_MIPS_HI16 and R_MIPS_GOT16 relocations should be followed by R_MIPS_LO16 relocation. To calculate result of R_MIPS_HI16 and R_MIPS_GOT16 relocations we need to combine addends from these relocations and paired R_MIPS_LO16 relocation.

Could you please review the patch? Any suggestions or objections are very appreciated.

Diff Detail

Event Timeline

Bigcheese requested changes to this revision.Nov 12 2013, 1:49 PM

Other than that it looks good here.

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
40

This isn't a great place for this as it preserves atom pointers from a specific pass, which are not guaranteed to be stable. It seems that it's only used for the local and global offsets of the got. I think a better option here would be to calculate the offsets in the layout by iterating over the final .got MergedSection.

lib/ReaderWriter/ELF/TargetHandler.h
125

No indentation.

130

No indentation.

lib/ReaderWriter/ELF/X86/X86TargetHandler.h
18 ↗(On Diff #5478)

This is an unrelated (and incorrect) change.

shankarke added inline comments.Nov 12 2013, 5:17 PM
lib/ReaderWriter/ELF/DefaultTargetHandler.h
62–78

remove all parameters to this function. alloc should be owned by the TargetHandler for Mips. name/order could be completely decided by Mips too.

lib/ReaderWriter/ELF/Mips/MipsELFTypes.h
1–20 ↗(On Diff #5478)

why does this need a separate header file ? This would go in MipsLinkingContext

lib/ReaderWriter/ELF/Mips/MipsGOT.cpp
90 ↗(On Diff #5478)

Why 2 + ?

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
61

not the right place for holding to the got.

72–74

move compareGOT outside the LinkingContext. The LinkingContext should just have just flags that determine what and how to link.

121–122

add else case and llvm_unreachable.

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
24–32

I dont like the interface that LinkingContext is having a lot of helper function. The LinkingContext contains only what and how the linking is done(mainly flags) and very few generic helper functions. This interface sounds like its not dealing with LinkingContext in that way.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
28–30

not sure what this comment is addressing.

32–33

the comments are describing parameters that are different in names.

40–41

the comments are describing parameters that are different in names.

45

nit pick. empty lines

73–75

the comments are describing parameters that are different in names. AHL is not being calculated here too.

84–85

the comments are describing parameters that are different in names.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
43–47

merge this private declaration with above. seen similiar declarations in other places too (protected ...)

lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
28

Didnt find a call to this function.

29–30

I thought you want to sort all the atoms in the symbolTable, why stable_sort ?

172

assert if these atoms are not found.

174

Why are you adding 0x7FF0, this might be difficult to support when we have linker script support.

lib/ReaderWriter/ELF/SectionChunks.h
608

I dont know what does the llvm guideline say with classes having two sets of protected fields, to reduce confusion, you might want to move to the same place where other protected members are.

613

unrelated change ?

990

same as previous.

1018–1020

an operator is better.

lib/ReaderWriter/ELF/TargetHandler.h
130

can we remove alloc and order here.

ruiu added inline comments.Nov 13 2013, 1:03 PM
lib/ReaderWriter/ELF/Mips/MipsELFTypes.h
17 ↗(On Diff #5478)

Is this the only architecture you're going to support? Should we name Mips32ELFType?

lib/ReaderWriter/ELF/Mips/MipsGOT.cpp
69 ↗(On Diff #5478)

s/auto/bool/

79 ↗(On Diff #5478)

I'd write like this instead of #ifndef

DEBUG_WITH_TYPE("MipsGOT", {
    ga->name = ...
    ...
    llvm::dbgs() << ...
 });

Note that it's probably better to use MipsGOT or something instead of GOT.

100 ↗(On Diff #5478)

No need to use #ifndef. DEBUG_WITH_TYPE will be expanded to do{}while(0) if NDEBUG is not defined.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
26

Why macro? Can it be an inline function?

34

In LLD local variables usually start with a lowercase letter.

189

nit: s.str() would flush the stream and then return the result string, so you can remove the line above.

lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
28

2^16 is too large. Typo of 4?

lib/ReaderWriter/ELF/Mips/MipsTarget.h
11

Do you really need this file?

lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
28

"ti" standed for "target info". Because LinkingContext used to be named TargetInfo, some local variables still contain "ti". It no longer makes sense. I'd think "ctx" is preferred.

Thanks for review. I put my answers and questions inline.

lib/ReaderWriter/ELF/DefaultTargetHandler.h
62–78

Just want to be sure that I understand you properly. Do you suggest to delete default implementations of createDynamicTable() and createDynamicSymbolTable() from the DefaultTargetHandler and define these functions as well as allocator in each target handlers for each supported targets (x86, x86_64, hexagon, mips etc)?

lib/ReaderWriter/ELF/Mips/MipsELFTypes.h
1–20 ↗(On Diff #5478)

OK

17 ↗(On Diff #5478)

Agree. I will rename it to the Mips32ElELFType.

lib/ReaderWriter/ELF/Mips/MipsGOT.cpp
69 ↗(On Diff #5478)

OK

79 ↗(On Diff #5478)

OK

90 ↗(On Diff #5478)

The GOT contains two reserved entries: lazy resolver and module pointer. But I agree that hardcoded constant is not a good solution. I will handle all GOT entries in a uniform way and remove this constant.

100 ↗(On Diff #5478)

OK

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
61

OK. I will fix that.

72–74

OK. I will fix that.

121–122

OK

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
24–32

OK. I will fix that.

40

OK. I will fix that.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
26

I will replace this macros by inline function.

28–30

OK. I will reformat comments for relocation handling function.

32–33

The comment mentions A and S, parameter's names are A and S. Where is the difference?

34

It looks like this rule is violated in the X86_64RelocationHandler.cpp and HexagonRelocationHandler.cpp. I know the reason - P, S, A names are used in the corresponding ABI specification. It simplify reading and understanding the code if we keep these names unchanged.

40–41

OK. I will fix that,

45

OK

73–75

OK. I will fix that.

84–85

OK. I will fix that.

189

OK. I will fix that.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
43–47

OK

lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
28

OK. I will fix that.

lib/ReaderWriter/ELF/Mips/MipsTarget.h
11

The lib/ReaderWriter/ELF/Targets.h includes xxxTarget.h files for each supported target. All these files look similar and include only xxxLinkingContext.h. I keep to the established order and do the same thing for the MIPS target.

lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
28

OutputELFWriter<ELFT>::buildDynamicSymbolTable()
and
SymbolTable<ELFT>::finalize()

29–30

I want to sort all atoms in the symbolTable which have corresponding entries in the global part of GOT. These atoms are subset of the symbolTable. So I do not want to change an order of other atoms.

172

OK

174

OK. I will move this constant to the separate function.

lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
28

OK. I will fix that.

lib/ReaderWriter/ELF/SectionChunks.h
608

OK. I will fix that.

613

Yes. I will fix that.

990

OK. I will fix that.

1018–1020

This time only MipsDynamicTable which is successor of DynamicTable needs access to the _entries. I will remove the DynamicTable::getEntry() method and move the DynamicTable::_entries field to the protected section.

lib/ReaderWriter/ELF/TargetHandler.h
125

OK. I will fix that.

130

OK. I will fix that.

lib/ReaderWriter/ELF/X86/X86TargetHandler.h
18 ↗(On Diff #5478)

OK. I will fix that.

atanasyan added inline comments.Nov 19 2013, 1:05 PM
lib/ReaderWriter/ELF/X86/X86TargetHandler.h
18 ↗(On Diff #5478)

I agree that this change is unrelated but I found rather strange things related to the X86TargetHandler class. This class is inherited from the DefaultTargetHandler class template which is instantiated using the X86ELFType type. The X86ELFType::MaxAlignment equals to 2. When we emit an ELF output file for X86 target we use a writer class inherited from the OutputELFWriter<ELFT> class where ELFT::MaxAlignment equals to 4. That is the strange thing number one. The strange thing number two is a constructor of the OutputELFWriter class. In this constructor (in case of X86 target) we make a dangerous cast. In fact we cast between different successor of the TargetHandlerBase class.

Is it a deliberate decision or mistake?

Bigcheese added inline comments.Nov 19 2013, 1:42 PM
lib/ReaderWriter/ELF/X86/X86TargetHandler.h
18 ↗(On Diff #5478)

Mistake. We should always use 2 byte alignment because of archives. Although the layout is exactly the same for both.

atanasyan added inline comments.Nov 20 2013, 4:51 AM
lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
40

It looks like my answer "I will fix that" was too optimistic.

I need to know a GOT content to perform the following actions:

  • Emit DT_MIPS_LOCAL_GOTNO (depends on number of local GOT entries) and DT_MIPS_GOTSYM (depends on number of global GOT entries) dynamic table tags.
  • Sort dynamic symbol table's atoms which have corresponding entries in the global part of GOT. The dynamic symbol entries should go at the same order as their GOT complements.
  • Initialize GOT entries related to the R_MIPS_GOT16 relocation. These GOT entries should be initialized by values calculated during the R_MIPS_GOT16 relocation processing. This action is not implemented in this patch.

Unfortunately I cannot figure out how to complete all these actions by iterating over the final .got MergedSection. Could you please provide more hints?

shankarke added inline comments.Nov 20 2013, 8:46 AM
lib/ReaderWriter/ELF/DefaultTargetHandler.h
62–78

createDynamicTable would just return DynamicTable<ELFT> section.

If the targets override that functionality they could return a DynamicTable<ELFT> section. All the required parameters needed for creating the Target specific DynamicTable section is present in the TargetHandler.

shankarke added inline comments.Nov 20 2013, 8:51 AM
lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
40

You could override createSection/createDynamicTable in the TargetLayout/TargetHandler respecitively. With this the Mips Target is in complete control of how the section gets written. Will this work ?

Bigcheese added inline comments.Nov 20 2013, 1:29 PM
lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
40

You should sort the GOT atoms after they are all created in a pass. Then iterate over them in the writer to get the counts.

Then use a custom dynamic symbol table section impl that sorts the same way.

atanasyan added inline comments.Nov 25 2013, 5:10 AM
lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
40

For dynamic symbol table sorting I need to get a GOT entry position for the given symbol. What is the best way to maintain a mapping between GOT atom and corresponding symbol? Is it OK to add a reference to the symbol for pointing to the GOT atom?

atanasyan updated this revision to Unknown Object (????).Dec 10 2013, 7:10 AM

Could you please review the new patch? I hope all issues found on the previous review iteration have been resolved.

Apart from the comments above, LGTM.

lib/ReaderWriter/ELF/DefaultLayout.h
201–207

You may want to remove this duplicate function.

lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
106

You could use the same function findOutputSection by removing const.

ruiu added a comment.Dec 12 2013, 1:54 AM

LGTM with a few comments. Please run clang-format on your patch before submitting.

lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
59

eti -> ctx?

124

You might want to add llvm_unreachable for other cases.

137

Add parentheses around the right hand side of the assignment for readabililty.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
24

Is "|" correct? I don't know about MIPS relocation types but in COFF it's "+".

atanasyan added inline comments.Dec 12 2013, 7:08 AM
lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
124

Not all MIPS relocation require GOT entries so it is ok to do nothing in this method sometimes. That is why I prefer to keep this code unchanged.

lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
24

Yes, "|" is correct. By the way the same code are in the Hexagon and X86_64 ELF targets.

shankarke accepted this revision.Jan 28 2014, 1:21 PM
atanasyan abandoned this revision.Apr 6 2014, 1:33 AM

Abandon this revision to cleanup the "Waiting on Others" list. The significantly rewritten patch has been committed at rL197342.