// Write one member out to the file.
bool
Archive::writeMember(
  const ArchiveMember& member,
  raw_fd_ostream& ARFile,
  std::string* ErrMsg
) {

  uint64_t filepos = ARFile.tell();
  filepos -= 8;

  // Get the data and its size either from the
  // member's in-memory data or directly from the file.
  size_t fSize = member.getSize();
  const char *data = (const char*)member.getData();
  MemoryBuffer *mFile = 0;
  if (!data) {
    ErrorOr<std::unique_ptr<MemoryBuffer> > FileOrErr =
        MemoryBuffer::getFile(member.getPath());
    if (!FileOrErr) {
      if (ErrMsg)
        *ErrMsg = FileOrErr.getError().message();
      return true;
    }
    mFile = FileOrErr.get().release();
    data = mFile->getBufferStart();
    fSize = mFile->getBufferSize();
  }

  int hdrSize = fSize;

  // Compute the fields of the header
  ArchiveMemberHeader Hdr;
  bool writeLongName = fillHeader(member,Hdr,hdrSize);

  // Write header to archive file
  ARFile.write((char*)&Hdr, sizeof(Hdr));

  // Write the long filename if its long
  if (writeLongName) {
    StringRef Name = sys::path::filename(member.getPath());
    ARFile.write(Name.data(), Name.size());
  }

  // Write the (possibly compressed) member's content to the file.
  ARFile.write(data,fSize);

  // Make sure the member is an even length
  if ((ARFile.tell() & 1) == 1)
    ARFile << ARFILE_PAD;

  // Close the mapped file if it was opened
  delete mFile;
  return false;
}
  void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
    // If the current section has size one, that means that the content we are
    // interested in is the file itself. Otherwise it is the content of the
    // section.
    //
    // TODO: Instead of copying the input file as is, deactivate the section
    // that is no longer needed.

    StringRef Content;
    CurrentSection->getContents(Content);

    if (Content.size() < 2)
      OS.write(Input.getBufferStart(), Input.getBufferSize());
    else
      OS.write(Content.data(), Content.size());
  }
/// Write 8-byte integers to a buffer in little-endian format.
static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) {
  for (unsigned i = 0; i < 8; ++i) {
    char Char = (char)(Val & 0xffu);
    OS.write(&Char, 1);
    Val >>= 8;
  }
}
static void printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
                                 const sys::TimeValue &ModTime, unsigned UID,
                                 unsigned GID, unsigned Perms, unsigned Size) {
  uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
  // Pad so that even 64 bit object files are aligned.
  unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
  unsigned NameWithPadding = Name.size() + Pad;
  printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
                          NameWithPadding + Size);
  Out << Name;
  assert(PosAfterHeader == Out.tell());
  while (Pad--)
    Out.write(uint8_t(0));
}
示例#5
0
// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
                 ArrayRef<NewArchiveMember> Members,
                 std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) {
  unsigned HeaderStartOffset = 0;
  unsigned BodyStartOffset = 0;
  SmallString<128> NameBuf;
  raw_svector_ostream NameOS(NameBuf);
  LLVMContext Context;
  for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
    MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef();
    Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr) {
      // FIXME: check only for "not an object file" errors.
      consumeError(ObjOrErr.takeError());
      continue;
    }
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!HeaderStartOffset) {
      HeaderStartOffset = Out.tell();
      if (Kind == object::Archive::K_GNU)
        printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0);
      else
        printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0);
      BodyStartOffset = Out.tell();
      print32(Out, Kind, 0); // number of entries or bytes
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;

      unsigned NameOffset = NameOS.tell();
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      MemberOffsetRefs.push_back(MemberNum);
      if (Kind == object::Archive::K_BSD)
        print32(Out, Kind, NameOffset);
      print32(Out, Kind, 0); // member offset
    }
  }

  if (HeaderStartOffset == 0)
    return 0;

  StringRef StringTable = NameOS.str();
  if (Kind == object::Archive::K_BSD)
    print32(Out, Kind, StringTable.size()); // byte count of the string table
  Out << StringTable;

  // ld64 requires the next member header to start at an offset that is
  // 4 bytes aligned.
  unsigned Pad = OffsetToAlignment(Out.tell(), 4);
  while (Pad--)
    Out.write(uint8_t(0));

  // Patch up the size of the symbol table now that we know how big it is.
  unsigned Pos = Out.tell();
  const unsigned MemberHeaderSize = 60;
  Out.seek(HeaderStartOffset + 48); // offset of the size field.
  printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10);

  // Patch up the number of symbols.
  Out.seek(BodyStartOffset);
  unsigned NumSyms = MemberOffsetRefs.size();
  if (Kind == object::Archive::K_GNU)
    print32(Out, Kind, NumSyms);
  else
    print32(Out, Kind, NumSyms * 8);

  Out.seek(Pos);
  return BodyStartOffset + 4;
}
 void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
   OS.write(Input.getBufferStart(), Input.getBufferSize());
 }
 void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
   assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
   StringRef FC = Input.getBuffer();
   OS.write(FC.data() + CurBundleInfo->second.Offset,
            CurBundleInfo->second.Size);
 }