Commit f2af0607 authored by Derek Schuff's avatar Derek Schuff
Browse files

[llvm-objcopy] Initial support for wasm in llvm-objcopy

Currently only supports simple copying, other operations to follow.

Reviewers: sbc100, alexshap, jhenderson

Differential Revision: https://reviews.llvm.org/D70930

This is a reland of a928d127 with a one-line fix to ensure that
the wasm version number is written as little-endian (it's the only
field in all of the binary format that's not a single byte or an
LEB, but we may have to watch out more when we start handling the
linking section).
parent 93cdd310
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ public:
  uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
  uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
  uint32_t getNumImportedEvents() const { return NumImportedEvents; }
  uint32_t getNumSections() const { return Sections.size(); }
  void moveSymbolNext(DataRefImpl &Symb) const override;

  uint32_t getSymbolFlags(DataRefImpl Symb) const override;
+90 −0
Original line number Diff line number Diff line
## Test a basic copy of an archive containing a wasm object.

# RUN: yaml2obj %s -o %t

## Create an archive and copy it using llvm-objcopy.
# RUN: rm -f %t.a
# RUN: llvm-ar crs %t.a %t
# RUN: cp %t.a %t.copy.a
# RUN: llvm-objcopy %t.a %t2.a
## Create another archive from an objcopy-copied object, verify that they match.
# RUN: llvm-objcopy %t %t2
# RUN: llvm-ar p %t2.a > %t3
# RUN: cmp %t2 %t3

## Check that the copied archive has the correct index contents.
# RUN: llvm-nm --print-armap %t.a | FileCheck --check-prefix=INDEX-TABLE %s
# RUN: llvm-nm --print-armap %t2.a | FileCheck --check-prefix=INDEX-TABLE %s
## Verify that llvm-objcopy has not modifed the input.
# RUN: cmp %t.copy.a %t.a

# INDEX-TABLE: Archive map
# INDEX-TABLE-NEXT: func1 in

## Do the same with an archive that has no index.
# RUN: rm -f %t.no.index.a
# RUN: llvm-ar crS %t.no.index.a %t
# RUN: llvm-objcopy %t.no.index.a %t2.no.index.a
# RUN: llvm-ar p %t2.no.index.a > %t4

# RUN: llvm-nm --print-armap %t.no.index.a | FileCheck --check-prefix=NO-INDEX-TABLE %s
# RUN: llvm-nm --print-armap %t2.no.index.a | FileCheck --check-prefix=NO-INDEX-TABLE %s
# RUN: cmp %t2 %t4

# NO-INDEX-TABLE-NOT: Archive map
# NO-INDEX-TABLE-NOT: func1 in

--- !WASM
FileHeader:
  Version: 0x00000001
Sections:
  - Type: TYPE
    Signatures:
      - Index: 0
        ParamTypes:
          - I32
        ReturnTypes:
          - F32
      - Index: 1
        ParamTypes:
          - I32
          - I64
        ReturnTypes:     []
  - Type: FUNCTION
    FunctionTypes:
      - 0
      - 1
  - Type: CODE
    Relocations:
      - Type:   R_WASM_TABLE_INDEX_SLEB
        Index:  0
        Offset: 0x00000002
      - Type:   R_WASM_FUNCTION_INDEX_LEB
        Index:  1
        Offset: 0x0000002
    Functions:
      - Index:  0
        Locals:
         - Type:  I32
           Count: 3
        Body: 010101010B
      - Index: 1
        Locals:
         - Type: I32
           Count: 1
        Body: 010101010B
  - Type: CUSTOM
    Name:    linking
    Version: 2
    SymbolTable:
      - Index: 0
        Kind:  FUNCTION
        Name:  func1
        Flags: [  ]
        Function: 0
      - Index: 1
        Kind:  FUNCTION
        Name:  func2
        Flags: [  ]
        Function: 1
...
+63 −0
Original line number Diff line number Diff line
## Test that the copied object has the same yaml conversion as the original.
## The copied object is not bit-identical to the yaml2obj-generated
## one, as yaml2obj uses 5-byte LEBs for section sizes (unlike objcopy/clang).
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-objcopy %t.o %t2.o
# RUN: obj2yaml %t.o > %t.yaml
# RUN: obj2yaml %t2.o > %t2.yaml
# RUN: diff %t.yaml %t2.yaml

--- !WASM
FileHeader:
  Version: 0x00000001
Sections:
  - Type: TYPE
    Signatures:
      - Index: 0
        ParamTypes:
          - I32
        ReturnTypes:
          - F32
      - Index: 1
        ParamTypes:
          - I32
          - I64
        ReturnTypes:     []
  - Type: FUNCTION
    FunctionTypes:
      - 0
      - 1
  - Type: CODE
    Relocations:
      - Type:   R_WASM_TABLE_INDEX_SLEB
        Index:  0
        Offset: 0x00000002
      - Type:   R_WASM_FUNCTION_INDEX_LEB
        Index:  1
        Offset: 0x0000002
    Functions:
      - Index:  0
        Locals:
         - Type:  I32
           Count: 3
        Body: 010101010B
      - Index: 1
        Locals:
         - Type: I32
           Count: 1
        Body: 010101010B
  - Type: CUSTOM
    Name:    linking
    Version: 2
    SymbolTable:
      - Index: 0
        Kind:  FUNCTION
        Name:  func1
        Flags: [  ]
        Function: 0
      - Index: 1
        Kind: FUNCTION
        Name: func2
        Flags: [  ]
        Function: 1
...
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ add_llvm_tool(llvm-objcopy
  MachO/MachOWriter.cpp
  MachO/MachOLayoutBuilder.cpp
  MachO/Object.cpp
  wasm/Reader.cpp
  wasm/Writer.cpp
  wasm/WasmObjcopy.cpp
  DEPENDS
  ObjcopyOptsTableGen
  InstallNameToolOptsTableGen
+5 −1
Original line number Diff line number Diff line
@@ -8,10 +8,11 @@

#include "llvm-objcopy.h"
#include "Buffer.h"
#include "COFF/COFFObjcopy.h"
#include "CopyConfig.h"
#include "ELF/ELFObjcopy.h"
#include "COFF/COFFObjcopy.h"
#include "MachO/MachOObjcopy.h"
#include "wasm/WasmObjcopy.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,6 +26,7 @@
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
@@ -172,6 +174,8 @@ static Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In,
    return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out);
  else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In))
    return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out);
  else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In))
    return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out);
  else
    return createStringError(object_error::invalid_file_type,
                             "unsupported object file format");
Loading