This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Linkerscript: implemented BYTE/SHORT/LONG/QUAD commands.
ClosedPublic

Authored by grimar on Sep 22 2016, 8:36 AM.

Details

Summary

Previously our scripts handles these commands incorrectly. For example:

SECTIONS  {
  .foo : {
 *(.foo.1)
 BYTE(0x11)
...

We accepted the script above treating BYTE as input section description. These commands are used in the wild though, eg:
https://searchcode.com/codesearch/view/42878166/

The BYTE, SHORT, LONG, and QUAD commands store one, two, four, and eight bytes (respectively). After storing the bytes, the location counter is incremented by the number of bytes
stored.

Patch implements them.

Diff Detail

Event Timeline

grimar updated this revision to Diff 72178.Sep 22 2016, 8:36 AM
grimar retitled this revision from to [ELF] - Linkerscript: implemented BYTE/SHORT/QUAD commands..
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: llvm-commits, grimar, davide, evgeny777.
ruiu added inline comments.Sep 22 2016, 1:02 PM
ELF/LinkerScript.cpp
72–1

This

72–1

this needs comments.

73

this and

74–79

I don't think we need these enums. Can't this be

int Size = StringSwitch(Tok)
  .Case("BYTE", 1)
  .Case("SHORT", 2)
  ...

?

77

Don't we have a function to find an output section by name?

80–83

This code seems to write the bytes in the host endianess instead of the target endianness.

ELF/LinkerScript.h
11–1

It's time to add comments for each command.

AssignmentKind, // . = expr or <sym> = expr
OutputSectionKind,
InputSectionKind,
AssertKind, // ASSERT(expr)
BytesDataKind, // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr)
ELF/OutputSections.cpp
4

It needs a comment.

// Linker scripts may have BYTE()-family commands with which you
// can write arbitrary bytes to the output. Process them if any.
grimar updated this revision to Diff 72248.Sep 23 2016, 3:38 AM
grimar retitled this revision from [ELF] - Linkerscript: implemented BYTE/SHORT/QUAD commands. to [ELF] - Linkerscript: implemented BYTE/SHORT/LONG/QUAD commands..
grimar added inline comments.
ELF/LinkerScript.cpp
72–1

Done.

72–1

Done.

73

Done.

74–79

Done.

77

I do not think we have, I created new one, it can be reused in getFiller() in following patch.

80–83

Ah, right. Fixed.

ELF/LinkerScript.h
11–1

Done. (btw comments looks a bit displaced because are clang-formatted)

ELF/OutputSections.cpp
4

Done.

rafael added inline comments.Sep 23 2016, 4:52 AM
ELF/LinkerScript.h
16

This could just store a StringRef or ArrayRef, no?

We can compute the correct (target endian) representation upfront and simplify the remaining code.

grimar added inline comments.Sep 23 2016, 7:02 AM
ELF/LinkerScript.h
16

Not sure about StringRef/ArrayRef, that could be std::vector<uint_8t>, computed in theory, but I think I can't do it.

Problem is that readBytesDataCommand() that reads command know nothing about target endianess because is not ELFT templated.

And I mean it is too early to know it as script can go before any other files, so I need to keep the value anyways, and in that case have a vector or something else in addition does not make much sence ?

rafael added inline comments.Sep 23 2016, 7:16 AM
ELF/LinkerScript.cpp
74

You can probably use getSectionIndex.

grimar updated this revision to Diff 72277.Sep 23 2016, 7:39 AM
  • Addressed review comments.
ELF/LinkerScript.cpp
713

Done.

rafael accepted this revision.Sep 23 2016, 10:35 AM
rafael edited edge metadata.

LGTM with nits, but wait so see if Rui is OK with it too.

test/ELF/linkerscript/data-commands.s
2

Add a big endian test.

21

Don't check the address.

This revision is now accepted and ready to land.Sep 23 2016, 10:35 AM
ruiu added inline comments.Sep 23 2016, 10:47 AM
ELF/LinkerScript.cpp
424

Add a blank line before this.

Maybe just

// Handle BYTE(), SHORT(), LONG(), or QUAD().
717

This looks odd. You can return early.

if (I == INT_MAX)
  return;
726

I'd factor this switch out as an independent functions so that we can do something like this here.

writeInt<ELFT>(Buf + DataCmd->Offset, DataCmd->Data, DataCmd->Size);

where writeInt is defined as

writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size);
1519

Use int instead of unsigned so to remove the cast to unsigned below.

grimar updated this revision to Diff 72454.Sep 26 2016, 3:34 AM
grimar edited edge metadata.
grimar marked 2 inline comments as done.
  • Addressed review comments.
ELF/LinkerScript.cpp
424

Done.

717

Done.

1519

Done.

test/ELF/linkerscript/data-commands.s
2

Done.

21

Done.

ruiu accepted this revision.Sep 26 2016, 10:43 AM
ruiu edited edge metadata.

LGTM with a nit.

ELF/LinkerScript.cpp
105–106

This comment doesn't make sense to be written here. Probably I'd just remove.

This revision was automatically updated to reflect the committed changes.
grimar added inline comments.Sep 26 2016, 12:45 PM
ELF/LinkerScript.cpp
105–106

Yeah, initially I wrote it because we have comment for filler saying it works with big-endian,
but for this place there is no disagree between ld, gold and spec, so it was probably excessive, I removed it from commit.