This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Add basic support for PPC LE
ClosedPublic

Authored by syzaara on Mar 14 2018, 11:09 AM.

Details

Summary

This patch adds changes to start supporting the Power 64-Bit ELF V2 ABI. This includes:

  • changing the ElfSym::GlobalOffsetTable to be named .TOC. rather than _GLOBAL_OFFSET_TABLE_
  • creating a GotHeader so the first entry in the .got is .TOC.
  • setting the e_flags to be 1 for ELF V1 and 2 for ELF V2

Diff Detail

Event Timeline

syzaara created this revision.Mar 14 2018, 11:09 AM
ruiu added inline comments.Mar 14 2018, 11:22 AM
lld/ELF/Arch/PPC64.cpp
90

Maybe you should template PPC64 class with ELFT? We do that for MIPS, and it's working fine. By doing that, we can remove this kind of switch completely.

lld/ELF/SyntheticSections.cpp
632–634

Assigning to a value and then immediately returning the value seems odd.

641

Please use clang-format to format a patch.

lld/ELF/Writer.cpp
194–196

Don't you need _GLOBAL_OFFSET_TABLE_ for PPC? If so, why? What is .TOC. and what is a role of the symbol? They need to be explained so that a first-time reader can understand the intention of the code.

syzaara updated this revision to Diff 138434.Mar 14 2018, 12:26 PM
syzaara added inline comments.Mar 14 2018, 12:28 PM
lld/ELF/Arch/PPC64.cpp
90

Our plan is to remove the BE/ELFv1 support so we won't need to template the PPC64 class.

ruiu added inline comments.Mar 14 2018, 12:31 PM
lld/ELF/Arch/PPC64.cpp
90

Is Hal OK with that?

sfertile added inline comments.Mar 14 2018, 1:28 PM
lld/ELF/Arch/PPC64.cpp
90

I've pinged Hal about this in IRC but didn't get a response. Hopefully he can chime in here.

I think since we are specifically implementing abi version 2 which (as far as I am aware) is only used on little-endian chips, then it makes sense to make these limitations explicit. Since there is already some functionality for the BE V1 abi, we decided it was best to leave it enabled at the start, but once we could replace all the existing testing with the V2 abi equivalent we would disable/remove the PPC64BE target. That isn't to say that we can't add support for the V1 abi and big-endian later, just that until a conscious effort it made to support the V1 abi as well it we would be best to remove it.

ruiu added inline comments.Mar 14 2018, 1:43 PM
lld/ELF/Arch/PPC64.cpp
90

I agree with that. There's no point to use a template to make it work for both LE and BE even though we only do support LE. We should also remove BE v1 ABI if it is absolutely necessary because I believe that the current v1 LE ABI support is somewhat incomplete and not really usable for linking regular day-to-day programs.

Could you please leave a comment here saying that we are currently handling both ELF64LE and ELF64BE but eventually we'll remove BE support once v2 ABI support is complete?

I'd wait for Hal's response though.

96–98

If you do like this you could eliminate the reassignments to the local variable.

if (EFlags =
      cast<ObjFile<ELF64BE>>(ObjectFiles[0])->getObj().getHeader()->e_flags)
  return EFlags;
return 1;
ruiu added inline comments.Mar 14 2018, 1:47 PM
lld/ELF/Writer.cpp
195–196

It is perhaps more accurate to say that PPC uses a different symbol name for _GLOBAL_OFFSET_TABLE_ and it's called ".TOC.". But I wonder why...

201–202

I'd make it more explicit that we are doing the same thing except choosing the name:

ElfSym::GlobalOffsetTable = addOptionalRegular(
      (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_",
      Out::ElfHeader, Target->GotBaseSymOff);
hfinkel added inline comments.Mar 14 2018, 1:57 PM
lld/ELF/Arch/PPC64.cpp
90

I agree. I never had time to get the BE implementation beyond the "hello world" stage (and, evidently, neither did anyone else). Let's remove it, do the LE ABIv2 implementation, and then if we want to add BE ABIv1 support later, we can figure out how to do that at that point.

syzaara updated this revision to Diff 138588.Mar 15 2018, 11:11 AM
ruiu added inline comments.Mar 15 2018, 11:27 AM
lld/ELF/Arch/PPC64.cpp
93

Please remove this and define inside if to narrow the scope of the local variables. There's no point to define a local variable early in C89 style.

99

I mean I'd do this:

if (uint32_t EFlags =
lld/ELF/SyntheticSections.cpp
632

This condition is always true on PPC64LE because GotHeaderEntriesNum is set to 1. That means you'll always have a .got even if you are creating static binaries. Is this really correct?

lld/ELF/Writer.cpp
193

Do you know why PPC64LE is using a different name? I mean if you can't find a reason, that's fine, but if that's the case, I'd leave a comment here saying that I don't know why, but .TOC. is defined by PPC64 v2 ABI spec as such, and the spec doesn't say anything about _GLOBAL_OFFSET_TABLE_.

sfertile added inline comments.Mar 15 2018, 11:44 AM
lld/ELF/Writer.cpp
195–196

The 32bit ppc elf abi supplement defined small data and small bss sections which held (local) data that could be accessed within a 16 bit offset of a _SDA_BASE_ pointer. In shared objects I think _SDA_BASE_ had the same value as _GLOBAL_OFFSET_TABLE_. In an executable _SDA_BASE_ would be loaded into an abi specified register and that register would hold that value for the life of the program.

The 64-bit PowerOpen ABI defined a TableOfContents (TOC) section which combined the typical elf GOT with the small data sections. The .TOC. symbol replaces both _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32bit abi.

There are a couple things related to the TOC we need to document in the PPC64 target:

  1. What is the TOC and how it differs from the GOT.
  2. The differences between .toc section , .TOC. symbol, Table of Contents (TOC) and TOC Base.
  3. How the various code models affect addressing using the TOC.

I would prefer to do these in a subsequent patch, but I think its pretty reasonable to add #1 in this patch if you prefer.

ruiu added a comment.Mar 15 2018, 1:10 PM

I'd really appreciate if you add these facts as comments as you add code for ppc64le rather than doing it later, as documentation is sometimes more important than actual code for this kind of low-level stuff that's built on top of a long history. We often find that everybody's doing something (e.g. using a different symbol name for something) but hard to figure out if that's an coincidence, cargo culting, undocumented ABI, or a part of a documented ABI. Writing a comment with a bit of background history will be extremely useful when we will have to revisit code we are writing today. In fact, I think we should write patches as if we were not only writing code but a book describing what the linker is.

I'd really appreciate if you add these facts as comments as you add code for ppc64le rather than doing it later, as documentation is sometimes more important than actual code for this kind of low-level stuff that's built on top of a long history. We often find that everybody's doing something (e.g. using a different symbol name for something) but hard to figure out if that's an coincidence, cargo culting, undocumented ABI, or a part of a documented ABI. Writing a comment with a bit of background history will be extremely useful when we will have to revisit code we are writing today. In fact, I think we should write patches as if we were not only writing code but a book describing what the linker is.

I think thats a great way to look at it. The reason we were holding off on adding some of that documentation is because we have a good understanding of the current (V2) ABI, so we know how things work today, but we really don't have any of the historical knowledge so we don't really know why the abi chooses to do these things differently. I agree with your reasoning though, we are better off to document what we know now and then we can always refine it in later patches.

syzaara updated this revision to Diff 138719.Mar 16 2018, 8:51 AM
syzaara added inline comments.Mar 16 2018, 8:58 AM
lld/ELF/SyntheticSections.cpp
632

This is incorrect, we only want to have .got if the .TOC. symbol is used which is already handled in the if statement with !(ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt);

ruiu accepted this revision.Mar 16 2018, 3:52 PM

LGTM

I think thats a great way to look at it. The reason we were holding off on adding some of that documentation is because we have a good understanding of the current (V2) ABI, so we know how things work today, but we really don't have any of the historical knowledge so we don't really know why the abi chooses to do these things differently. I agree with your reasoning though, we are better off to document what we know now and then we can always refine it in later patches.

Thank you for your understanding. We don't have to figure out and justify every detail of the spec because some facts have really been lost in history, but still, writing honest comments about what we know and don't know today will be extremely useful in the future. For example, instead of just saying "_GLOBAL_OFFSET_TABLE_ is not defined in ppc but we have .TOC instead", we can say (I don't think the statement is correct, but as an example) "_GLOBAL_OFFSET_TABLE_ is not defined in ppc but we have .TOC instead. These symbols serve a similar purpose, and .TOC. is defined as +0x8000 from the beginning global offset table. We don't know the exact reason why ppc defined its own symbol name instead of using _GLOBAL_OFFSET_TABLE_, but that existed from the first version of PPC ABI, so we need to define that symbol." I really like that kind of comment because it is more convincing to me that the author of the code understood what they were doing.

Anyways, thank you for the first patch! Please submit.

This revision is now accepted and ready to land.Mar 16 2018, 3:52 PM
This revision was automatically updated to reflect the committed changes.
This revision was automatically updated to reflect the committed changes.