<commit_before>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Config.h"
#include "Driver.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/LTO/LTOCodeGenerator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>

using namespace llvm;

namespace lld {
namespace coff {

void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
  InputFile *File = FileP.get();
  Files.push_back(std::move(FileP));
  if (auto *F = dyn_cast<ArchiveFile>(File)) {
    ArchiveQueue.push_back(F);
    return;
  }
  ObjectQueue.push_back(File);
  if (auto *F = dyn_cast<ObjectFile>(File)) {
    ObjectFiles.push_back(F);
  } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
    BitcodeFiles.push_back(F);
  } else {
    ImportFiles.push_back(cast<ImportFile>(File));
  }
}

std::error_code SymbolTable::step() {
  if (queueEmpty())
    return std::error_code();
  if (auto EC = readObjects())
    return EC;
  if (auto EC = readArchives())
    return EC;
  return std::error_code();
}

std::error_code SymbolTable::run() {
  while (!queueEmpty())
    if (auto EC = step())
      return EC;
  return std::error_code();
}

std::error_code SymbolTable::readArchives() {
  if (ArchiveQueue.empty())
    return std::error_code();

  // Add lazy symbols to the symbol table. Lazy symbols that conflict
  // with existing undefined symbols are accumulated in LazySyms.
  std::vector<Symbol *> LazySyms;
  for (ArchiveFile *File : ArchiveQueue) {
    if (Config->Verbose)
      llvm::outs() << "Reading " << File->getShortName() << "\n";
    if (auto EC = File->parse())
      return EC;
    for (Lazy *Sym : File->getLazySymbols())
      addLazy(Sym, &LazySyms);
  }
  ArchiveQueue.clear();

  // Add archive member files to ObjectQueue that should resolve
  // existing undefined symbols.
  for (Symbol *Sym : LazySyms)
    if (auto EC = addMemberFile(cast<Lazy>(Sym->Body)))
      return EC;
  return std::error_code();
}

std::error_code SymbolTable::readObjects() {
  if (ObjectQueue.empty())
    return std::error_code();

  // Add defined and undefined symbols to the symbol table.
  std::vector<StringRef> Directives;
  for (size_t I = 0; I < ObjectQueue.size(); ++I) {
    InputFile *File = ObjectQueue[I];
    if (Config->Verbose)
      llvm::outs() << "Reading " << File->getShortName() << "\n";
    if (auto EC = File->parse())
      return EC;
    // Adding symbols may add more files to ObjectQueue
    // (but not to ArchiveQueue).
    for (SymbolBody *Sym : File->getSymbols())
      if (Sym->isExternal())
        if (auto EC = addSymbol(Sym))
          return EC;
    StringRef S = File->getDirectives();
    if (!S.empty())
      Directives.push_back(S);
  }
  ObjectQueue.clear();

  // Parse directive sections. This may add files to
  // ArchiveQueue and ObjectQueue.
  for (StringRef S : Directives)
    if (auto EC = Driver->parseDirectives(S))
      return EC;
  return std::error_code();
}

bool SymbolTable::queueEmpty() {
  return ArchiveQueue.empty() && ObjectQueue.empty();
}

bool SymbolTable::reportRemainingUndefines() {
  bool Ret = false;
  for (auto &I : Symtab) {
    Symbol *Sym = I.second;
    auto *Undef = dyn_cast<Undefined>(Sym->Body);
    if (!Undef)
      continue;
    StringRef Name = Undef->getName();
    // A weak alias may have been resolved, so check for that. A weak alias
    // may be a weak alias to another symbol, so check recursively.
    for (SymbolBody *A = Undef->WeakAlias; A;
         A = cast<Undefined>(A)->WeakAlias) {
      if (auto *D = dyn_cast<Defined>(A->repl())) {
        Sym->Body = D;
        goto next;
      }
    }
    // If we can resolve a symbol by removing __imp_ prefix, do that.
    // This odd rule is for compatibility with MSVC linker.
    if (Name.startswith("__imp_")) {
      Symbol *Imp = find(Name.substr(strlen("__imp_")));
      if (Imp && isa<Defined>(Imp->Body)) {
        auto *D = cast<Defined>(Imp->Body);
        auto *S = new (Alloc) DefinedLocalImport(Name, D);
        LocalImportChunks.push_back(S->getChunk());
        Sym->Body = S;
        continue;
      }
    }
    llvm::errs() << "undefined symbol: " << Name << "\n";
    // Remaining undefined symbols are not fatal if /force is specified.
    // They are replaced with dummy defined symbols.
    if (Config->Force) {
      Sym->Body = new (Alloc) DefinedAbsolute(Name, 0);
      continue;
    }
    Ret = true;
    next:;
  }
  return Ret;
}

void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return;
  SymbolBody *Existing = Sym->Body;
  if (!isa<Undefined>(Existing))
    return;
  Sym->Body = New;
  New->setBackref(Sym);
  Accum->push_back(Sym);
}

std::error_code SymbolTable::addSymbol(SymbolBody *New) {
  // Find an existing symbol or create and insert a new one.
  assert(isa<Defined>(New) || isa<Undefined>(New));
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return std::error_code();
  SymbolBody *Existing = Sym->Body;

  // If we have an undefined symbol and a lazy symbol,
  // let the lazy symbol to read a member file.
  if (auto *L = dyn_cast<Lazy>(Existing)) {
    // Undefined symbols with weak aliases need not to be resolved,
    // since they would be replaced with weak aliases if they remain
    // undefined.
    if (auto *U = dyn_cast<Undefined>(New))
      if (!U->WeakAlias)
        return addMemberFile(L);
    Sym->Body = New;
    return std::error_code();
  }

  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
  // equivalent (conflicting), or more preferable, respectively.
  int Comp = Existing->compare(New);
  if (Comp == 0) {
    llvm::errs() << "duplicate symbol: " << Existing->getDebugName()
                 << " and " << New->getDebugName() << "\n";
    return make_error_code(LLDError::DuplicateSymbols);
  }
  if (Comp < 0)
    Sym->Body = New;
  return std::error_code();
}

Symbol *SymbolTable::insert(SymbolBody *New) {
  Symbol *&Sym = Symtab[New->getName()];
  if (Sym) {
    New->setBackref(Sym);
    return Sym;
  }
  Sym = new (Alloc) Symbol(New);
  New->setBackref(Sym);
  return Sym;
}

// Reads an archive member file pointed by a given symbol.
std::error_code SymbolTable::addMemberFile(Lazy *Body) {
  auto FileOrErr = Body->getMember();
  if (auto EC = FileOrErr.getError())
    return EC;
  std::unique_ptr<InputFile> File = std::move(FileOrErr.get());

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (!File)
    return std::error_code();
  if (Config->Verbose)
    llvm::outs() << "Loaded " << File->getShortName() << " for "
                 << Body->getName() << "\n";
  addFile(std::move(File));
  return std::error_code();
}

std::vector<Chunk *> SymbolTable::getChunks() {
  std::vector<Chunk *> Res;
  for (ObjectFile *File : ObjectFiles) {
    std::vector<Chunk *> &V = File->getChunks();
    Res.insert(Res.end(), V.begin(), V.end());
  }
  return Res;
}

Symbol *SymbolTable::find(StringRef Name) {
  auto It = Symtab.find(Name);
  if (It == Symtab.end())
    return nullptr;
  return It->second;
}

void SymbolTable::mangleMaybe(Undefined *U) {
  if (U->WeakAlias)
    return;
  if (!isa<Undefined>(U->repl()))
    return;

  // In Microsoft ABI, a non-member function name is mangled this way.
  std::string Prefix = ("?" + U->getName() + "@@Y").str();
  for (auto Pair : Symtab) {
    StringRef Name = Pair.first;
    if (!Name.startswith(Prefix))
      continue;
    U->WeakAlias = addUndefined(Name);
    return;
  }
}

Undefined *SymbolTable::addUndefined(StringRef Name) {
  auto *New = new (Alloc) Undefined(Name);
  addSymbol(New);
  if (auto *U = dyn_cast<Undefined>(New->repl()))
    return U;
  return New;
}

void SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
  addSymbol(new (Alloc) DefinedAbsolute(Name, VA));
}

void SymbolTable::printMap(llvm::raw_ostream &OS) {
  for (ObjectFile *File : ObjectFiles) {
    OS << File->getShortName() << ":\n";
    for (SymbolBody *Body : File->getSymbols())
      if (auto *R = dyn_cast<DefinedRegular>(Body))
        if (R->isLive())
          OS << Twine::utohexstr(Config->ImageBase + R->getRVA())
             << " " << R->getName() << "\n";
  }
}

std::error_code SymbolTable::addCombinedLTOObject() {
  if (BitcodeFiles.empty())
    return std::error_code();

  // Create an object file and add it to the symbol table by replacing any
  // DefinedBitcode symbols with the definitions in the object file.
  LTOCodeGenerator CG;
  auto FileOrErr = createLTOObject(&CG);
  if (auto EC = FileOrErr.getError())
    return EC;
  ObjectFile *Obj = FileOrErr.get();

  for (SymbolBody *Body : Obj->getSymbols()) {
    if (!Body->isExternal())
      continue;
    // Find an existing Symbol. We should not see any new undefined symbols at
    // this point.
    StringRef Name = Body->getName();
    Symbol *Sym = insert(Body);
    if (Sym->Body == Body && !isa<Defined>(Body)) {
      llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
      return make_error_code(LLDError::BrokenFile);
    }

    if (isa<DefinedBitcode>(Sym->Body)) {
      // The symbol should now be defined.
      if (!isa<Defined>(Body)) {
        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
        return make_error_code(LLDError::BrokenFile);
      }
      Sym->Body = Body;
      continue;
    }
    if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
      // We may see new references to runtime library symbols such as __chkstk
      // here. These symbols must be wholly defined in non-bitcode files.
      if (auto EC = addMemberFile(L))
        return EC;
      continue;
    }
    SymbolBody *Existing = Sym->Body;
    int Comp = Existing->compare(Body);
    if (Comp == 0) {
      llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
      return make_error_code(LLDError::BrokenFile);
    }
    if (Comp < 0)
      Sym->Body = Body;
  }

  size_t NumBitcodeFiles = BitcodeFiles.size();
  if (auto EC = run())
    return EC;
  if (BitcodeFiles.size() != NumBitcodeFiles) {
    llvm::errs() << "LTO: late loaded symbol created new bitcode reference\n";
    return make_error_code(LLDError::BrokenFile);
  }

  // New runtime library symbol references may have created undefined references.
  if (reportRemainingUndefines())
    return make_error_code(LLDError::BrokenFile);
  return std::error_code();
}

// Combine and compile bitcode files and then return the result
// as a regular COFF object file.
ErrorOr<ObjectFile *> SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
  // All symbols referenced by non-bitcode objects must be preserved.
  for (ObjectFile *File : ObjectFiles)
    for (SymbolBody *Body : File->getSymbols())
      if (auto *S = dyn_cast<DefinedBitcode>(Body->repl()))
        CG->addMustPreserveSymbol(S->getName());

  // Likewise for bitcode symbols which we initially resolved to non-bitcode.
  for (BitcodeFile *File : BitcodeFiles)
    for (SymbolBody *Body : File->getSymbols())
      if (isa<DefinedBitcode>(Body) && !isa<DefinedBitcode>(Body->repl()))
        CG->addMustPreserveSymbol(Body->getName());

  // Likewise for other symbols that must be preserved.
  for (Undefined *U : Config->GCRoot)
    if (isa<DefinedBitcode>(U->repl()))
      CG->addMustPreserveSymbol(U->getName());

  CG->setModule(BitcodeFiles[0]->releaseModule());
  for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
    CG->addModule(BitcodeFiles[I]->getModule());

  std::string ErrMsg;
  LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership
  if (!LTOMB) {
    llvm::errs() << ErrMsg << '\n';
    return make_error_code(LLDError::BrokenFile);
  }
  auto *Obj = new ObjectFile(LTOMB->getMemBufferRef());
  Files.emplace_back(Obj);
  ObjectFiles.push_back(Obj);
  if (auto EC = Obj->parse())
    return EC;
  return Obj;
}

} // namespace coff
} // namespace lld
<commit_msg>COFF: Print directive section contents if /verbose.<commit_after>//===- SymbolTable.cpp ----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Config.h"
#include "Driver.h"
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/LTO/LTOCodeGenerator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>

using namespace llvm;

namespace lld {
namespace coff {

void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
  InputFile *File = FileP.get();
  Files.push_back(std::move(FileP));
  if (auto *F = dyn_cast<ArchiveFile>(File)) {
    ArchiveQueue.push_back(F);
    return;
  }
  ObjectQueue.push_back(File);
  if (auto *F = dyn_cast<ObjectFile>(File)) {
    ObjectFiles.push_back(F);
  } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
    BitcodeFiles.push_back(F);
  } else {
    ImportFiles.push_back(cast<ImportFile>(File));
  }
}

std::error_code SymbolTable::step() {
  if (queueEmpty())
    return std::error_code();
  if (auto EC = readObjects())
    return EC;
  if (auto EC = readArchives())
    return EC;
  return std::error_code();
}

std::error_code SymbolTable::run() {
  while (!queueEmpty())
    if (auto EC = step())
      return EC;
  return std::error_code();
}

std::error_code SymbolTable::readArchives() {
  if (ArchiveQueue.empty())
    return std::error_code();

  // Add lazy symbols to the symbol table. Lazy symbols that conflict
  // with existing undefined symbols are accumulated in LazySyms.
  std::vector<Symbol *> LazySyms;
  for (ArchiveFile *File : ArchiveQueue) {
    if (Config->Verbose)
      llvm::outs() << "Reading " << File->getShortName() << "\n";
    if (auto EC = File->parse())
      return EC;
    for (Lazy *Sym : File->getLazySymbols())
      addLazy(Sym, &LazySyms);
  }
  ArchiveQueue.clear();

  // Add archive member files to ObjectQueue that should resolve
  // existing undefined symbols.
  for (Symbol *Sym : LazySyms)
    if (auto EC = addMemberFile(cast<Lazy>(Sym->Body)))
      return EC;
  return std::error_code();
}

std::error_code SymbolTable::readObjects() {
  if (ObjectQueue.empty())
    return std::error_code();

  // Add defined and undefined symbols to the symbol table.
  std::vector<StringRef> Directives;
  for (size_t I = 0; I < ObjectQueue.size(); ++I) {
    InputFile *File = ObjectQueue[I];
    if (Config->Verbose)
      llvm::outs() << "Reading " << File->getShortName() << "\n";
    if (auto EC = File->parse())
      return EC;
    // Adding symbols may add more files to ObjectQueue
    // (but not to ArchiveQueue).
    for (SymbolBody *Sym : File->getSymbols())
      if (Sym->isExternal())
        if (auto EC = addSymbol(Sym))
          return EC;
    StringRef S = File->getDirectives();
    if (!S.empty()) {
      Directives.push_back(S);
      if (Config->Verbose)
        llvm::outs() << "Directives: " << File->getShortName()
                     << ": " << S << "\n";
    }
  }
  ObjectQueue.clear();

  // Parse directive sections. This may add files to
  // ArchiveQueue and ObjectQueue.
  for (StringRef S : Directives)
    if (auto EC = Driver->parseDirectives(S))
      return EC;
  return std::error_code();
}

bool SymbolTable::queueEmpty() {
  return ArchiveQueue.empty() && ObjectQueue.empty();
}

bool SymbolTable::reportRemainingUndefines() {
  bool Ret = false;
  for (auto &I : Symtab) {
    Symbol *Sym = I.second;
    auto *Undef = dyn_cast<Undefined>(Sym->Body);
    if (!Undef)
      continue;
    StringRef Name = Undef->getName();
    // A weak alias may have been resolved, so check for that. A weak alias
    // may be a weak alias to another symbol, so check recursively.
    for (SymbolBody *A = Undef->WeakAlias; A;
         A = cast<Undefined>(A)->WeakAlias) {
      if (auto *D = dyn_cast<Defined>(A->repl())) {
        Sym->Body = D;
        goto next;
      }
    }
    // If we can resolve a symbol by removing __imp_ prefix, do that.
    // This odd rule is for compatibility with MSVC linker.
    if (Name.startswith("__imp_")) {
      Symbol *Imp = find(Name.substr(strlen("__imp_")));
      if (Imp && isa<Defined>(Imp->Body)) {
        auto *D = cast<Defined>(Imp->Body);
        auto *S = new (Alloc) DefinedLocalImport(Name, D);
        LocalImportChunks.push_back(S->getChunk());
        Sym->Body = S;
        continue;
      }
    }
    llvm::errs() << "undefined symbol: " << Name << "\n";
    // Remaining undefined symbols are not fatal if /force is specified.
    // They are replaced with dummy defined symbols.
    if (Config->Force) {
      Sym->Body = new (Alloc) DefinedAbsolute(Name, 0);
      continue;
    }
    Ret = true;
    next:;
  }
  return Ret;
}

void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return;
  SymbolBody *Existing = Sym->Body;
  if (!isa<Undefined>(Existing))
    return;
  Sym->Body = New;
  New->setBackref(Sym);
  Accum->push_back(Sym);
}

std::error_code SymbolTable::addSymbol(SymbolBody *New) {
  // Find an existing symbol or create and insert a new one.
  assert(isa<Defined>(New) || isa<Undefined>(New));
  Symbol *Sym = insert(New);
  if (Sym->Body == New)
    return std::error_code();
  SymbolBody *Existing = Sym->Body;

  // If we have an undefined symbol and a lazy symbol,
  // let the lazy symbol to read a member file.
  if (auto *L = dyn_cast<Lazy>(Existing)) {
    // Undefined symbols with weak aliases need not to be resolved,
    // since they would be replaced with weak aliases if they remain
    // undefined.
    if (auto *U = dyn_cast<Undefined>(New))
      if (!U->WeakAlias)
        return addMemberFile(L);
    Sym->Body = New;
    return std::error_code();
  }

  // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
  // equivalent (conflicting), or more preferable, respectively.
  int Comp = Existing->compare(New);
  if (Comp == 0) {
    llvm::errs() << "duplicate symbol: " << Existing->getDebugName()
                 << " and " << New->getDebugName() << "\n";
    return make_error_code(LLDError::DuplicateSymbols);
  }
  if (Comp < 0)
    Sym->Body = New;
  return std::error_code();
}

Symbol *SymbolTable::insert(SymbolBody *New) {
  Symbol *&Sym = Symtab[New->getName()];
  if (Sym) {
    New->setBackref(Sym);
    return Sym;
  }
  Sym = new (Alloc) Symbol(New);
  New->setBackref(Sym);
  return Sym;
}

// Reads an archive member file pointed by a given symbol.
std::error_code SymbolTable::addMemberFile(Lazy *Body) {
  auto FileOrErr = Body->getMember();
  if (auto EC = FileOrErr.getError())
    return EC;
  std::unique_ptr<InputFile> File = std::move(FileOrErr.get());

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (!File)
    return std::error_code();
  if (Config->Verbose)
    llvm::outs() << "Loaded " << File->getShortName() << " for "
                 << Body->getName() << "\n";
  addFile(std::move(File));
  return std::error_code();
}

std::vector<Chunk *> SymbolTable::getChunks() {
  std::vector<Chunk *> Res;
  for (ObjectFile *File : ObjectFiles) {
    std::vector<Chunk *> &V = File->getChunks();
    Res.insert(Res.end(), V.begin(), V.end());
  }
  return Res;
}

Symbol *SymbolTable::find(StringRef Name) {
  auto It = Symtab.find(Name);
  if (It == Symtab.end())
    return nullptr;
  return It->second;
}

void SymbolTable::mangleMaybe(Undefined *U) {
  if (U->WeakAlias)
    return;
  if (!isa<Undefined>(U->repl()))
    return;

  // In Microsoft ABI, a non-member function name is mangled this way.
  std::string Prefix = ("?" + U->getName() + "@@Y").str();
  for (auto Pair : Symtab) {
    StringRef Name = Pair.first;
    if (!Name.startswith(Prefix))
      continue;
    U->WeakAlias = addUndefined(Name);
    return;
  }
}

Undefined *SymbolTable::addUndefined(StringRef Name) {
  auto *New = new (Alloc) Undefined(Name);
  addSymbol(New);
  if (auto *U = dyn_cast<Undefined>(New->repl()))
    return U;
  return New;
}

void SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
  addSymbol(new (Alloc) DefinedAbsolute(Name, VA));
}

void SymbolTable::printMap(llvm::raw_ostream &OS) {
  for (ObjectFile *File : ObjectFiles) {
    OS << File->getShortName() << ":\n";
    for (SymbolBody *Body : File->getSymbols())
      if (auto *R = dyn_cast<DefinedRegular>(Body))
        if (R->isLive())
          OS << Twine::utohexstr(Config->ImageBase + R->getRVA())
             << " " << R->getName() << "\n";
  }
}

std::error_code SymbolTable::addCombinedLTOObject() {
  if (BitcodeFiles.empty())
    return std::error_code();

  // Create an object file and add it to the symbol table by replacing any
  // DefinedBitcode symbols with the definitions in the object file.
  LTOCodeGenerator CG;
  auto FileOrErr = createLTOObject(&CG);
  if (auto EC = FileOrErr.getError())
    return EC;
  ObjectFile *Obj = FileOrErr.get();

  for (SymbolBody *Body : Obj->getSymbols()) {
    if (!Body->isExternal())
      continue;
    // Find an existing Symbol. We should not see any new undefined symbols at
    // this point.
    StringRef Name = Body->getName();
    Symbol *Sym = insert(Body);
    if (Sym->Body == Body && !isa<Defined>(Body)) {
      llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
      return make_error_code(LLDError::BrokenFile);
    }

    if (isa<DefinedBitcode>(Sym->Body)) {
      // The symbol should now be defined.
      if (!isa<Defined>(Body)) {
        llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
        return make_error_code(LLDError::BrokenFile);
      }
      Sym->Body = Body;
      continue;
    }
    if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
      // We may see new references to runtime library symbols such as __chkstk
      // here. These symbols must be wholly defined in non-bitcode files.
      if (auto EC = addMemberFile(L))
        return EC;
      continue;
    }
    SymbolBody *Existing = Sym->Body;
    int Comp = Existing->compare(Body);
    if (Comp == 0) {
      llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
      return make_error_code(LLDError::BrokenFile);
    }
    if (Comp < 0)
      Sym->Body = Body;
  }

  size_t NumBitcodeFiles = BitcodeFiles.size();
  if (auto EC = run())
    return EC;
  if (BitcodeFiles.size() != NumBitcodeFiles) {
    llvm::errs() << "LTO: late loaded symbol created new bitcode reference\n";
    return make_error_code(LLDError::BrokenFile);
  }

  // New runtime library symbol references may have created undefined references.
  if (reportRemainingUndefines())
    return make_error_code(LLDError::BrokenFile);
  return std::error_code();
}

// Combine and compile bitcode files and then return the result
// as a regular COFF object file.
ErrorOr<ObjectFile *> SymbolTable::createLTOObject(LTOCodeGenerator *CG) {
  // All symbols referenced by non-bitcode objects must be preserved.
  for (ObjectFile *File : ObjectFiles)
    for (SymbolBody *Body : File->getSymbols())
      if (auto *S = dyn_cast<DefinedBitcode>(Body->repl()))
        CG->addMustPreserveSymbol(S->getName());

  // Likewise for bitcode symbols which we initially resolved to non-bitcode.
  for (BitcodeFile *File : BitcodeFiles)
    for (SymbolBody *Body : File->getSymbols())
      if (isa<DefinedBitcode>(Body) && !isa<DefinedBitcode>(Body->repl()))
        CG->addMustPreserveSymbol(Body->getName());

  // Likewise for other symbols that must be preserved.
  for (Undefined *U : Config->GCRoot)
    if (isa<DefinedBitcode>(U->repl()))
      CG->addMustPreserveSymbol(U->getName());

  CG->setModule(BitcodeFiles[0]->releaseModule());
  for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
    CG->addModule(BitcodeFiles[I]->getModule());

  std::string ErrMsg;
  LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership
  if (!LTOMB) {
    llvm::errs() << ErrMsg << '\n';
    return make_error_code(LLDError::BrokenFile);
  }
  auto *Obj = new ObjectFile(LTOMB->getMemBufferRef());
  Files.emplace_back(Obj);
  ObjectFiles.push_back(Obj);
  if (auto EC = Obj->parse())
    return EC;
  return Obj;
}

} // namespace coff
} // namespace lld
<|endoftext|>


<commit_before>#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
#include <queue>
#include <vector>
#include <map>

using namespace std;

struct fileCache{
    time_t timestamp;
    queue<string> statOutput;
};

void string_replacer(string&,const string,string);
queue<string> adb_push(string, string);
queue<string> adb_pull(string, string);
queue<string> adb_shell(string);
queue<string> shell(string);
queue<string> exec_command(string);
vector<string> make_array(string);
map<string,fileCache> fileData;

vector<string> make_array(string data){
    vector<string> result;
    string delimiters = " ";
    string::size_type lastPos = data.find_first_not_of(delimiters, 0);
    string::size_type pos     = data.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        result.push_back(data.substr(lastPos, pos - lastPos));
        lastPos = data.find_first_not_of(delimiters, pos);
        pos = data.find_first_of(delimiters, lastPos);
    }
    return result;
}

queue<string> shell(string command)
{
    string actual_command;
    string_replacer(command,"\\","\\\\");
    string_replacer(command,"'","\\'");
    string_replacer(command,"`","\\`");
    actual_command.append(command);

    return exec_command(actual_command);
}

queue<string> adb_shell(string command)
{
    string actual_command;
    string_replacer(command,"\\","\\\\");
    string_replacer(command,"'","\\'");
    string_replacer(command,"`","\\`");
    actual_command = "adb shell ";
    actual_command.append(command);
    //actual_command.append("'");

    return exec_command(actual_command);
}

queue<string> adb_pull(string remote_source, string local_destination)
{
    string actual_command;
    string_replacer(remote_source,"\\","\\\\");
    string_replacer(remote_source,"'","\\'");
    string_replacer(remote_source,"`","\\`");
    string_replacer(local_destination,"\\","\\\\");
    string_replacer(local_destination,"'","\\'");
    string_replacer(local_destination,"`","\\`");
    actual_command = "adb pull '";
    actual_command.append(remote_source);
    actual_command.append("' '");
    actual_command.append(local_destination);
    actual_command.append("'");

    return exec_command(actual_command);
}

queue<string> adb_push(string local_source, string remote_destination)
{
    string actual_command;
    string_replacer(remote_destination,"\\","\\\\");
    string_replacer(remote_destination,"'","\\'");
    string_replacer(remote_destination,"`","\\`");
    string_replacer(local_source,"\\","\\\\");
    string_replacer(local_source,"'","\\'");
    string_replacer(local_source,"`","\\`");
    actual_command = "adb push '";
    actual_command.append(local_source);
    actual_command.append("' '");
    actual_command.append(remote_destination);
    actual_command.append("'");

    return exec_command(actual_command);
}

queue<string> exec_command(string command)
{
    queue<string> output;
    FILE *fp = popen(command.c_str(), "r" );

    char buff[1000];
    string tmp_string;
    while ( fgets( buff, sizeof buff, fp ) != NULL && !feof(fp) )
    {
        tmp_string.assign(buff);
        tmp_string.erase(tmp_string.size()-2);
        output.push(tmp_string);
    }

    pclose( fp );

    return output;
}

void string_replacer( string &source, const string find, string replace ) {
	size_t j;
	for ( ; (j = source.find( find,j)) != string::npos ; ) {
		source.replace( j, find.length(), replace );
        j = j + replace.length();
	}
}

int xtoi(const char* xs, unsigned int* result)
{
 size_t szlen = strlen(xs);
 int i, xv, fact;

 if (szlen > 0)
 {
  // Converting more than 32bit hexadecimal value?
  if (szlen>8) return 2; // exit

  // Begin conversion here
  *result = 0;
  fact = 1;

  // Run until no more character to convert
  for(i=szlen-1; i>=0 ;i--)
  {
   if (isxdigit(*(xs+i)))
   {
    if (*(xs+i)>=97)
    {
     xv = ( *(xs+i) - 97) + 10;
    }
    else if ( *(xs+i) >= 65)
    {
     xv = (*(xs+i) - 65) + 10;
    }
    else
    {
     xv = *(xs+i) - 48;
    }
    *result += (xv * fact);
    fact *= 16;
   }
   else
   {
    // Conversion was abnormally terminated
    // by non hexadecimal digit, hence
    // returning only the converted with
    // an error value 4 (illegal hex character)
    return 4;
   }
  }
 }

 // Nothing to convert
 return 1;
}
static int adb_getattr(const char *path, struct stat *stbuf)
{
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));
    queue<string> output;
    string path_string;
    path_string.assign(path);
    string_replacer(path_string," ","\\ ");

    if (fileData.find(path_string) ==  fileData.end() || fileData[path_string].timestamp + 30 > time(NULL)){
        string command = "stat -t \"";
        command.append(path_string);
        command.append("\"");
        cout << command<<"\n";
        output = adb_shell(command);
        fileData[path_string].statOutput = output;
        fileData[path_string].timestamp = time(NULL);
    }else{
        output = fileData[path_string].statOutput;
        cout << "from cache " << output.front() <<"\n";
    }
    vector<string> output_chunk = make_array(output.front());
    if (output_chunk.size() < 13){
        return -ENOENT;
    }
    while (output_chunk.size() > 15){
        output_chunk.erase( output_chunk.begin());
    }
    /*
    stat -t Explained:
    file name (%n)
    total size (%s)
    number of blocks (%b)
    raw mode in hex (%f)
    UID of owner (%u)
    GID of file (%g)
    device number in hex (%D)
    inode number (%i)
    number of hard links (%h)
    major devide type in hex (%t)
    minor device type in hex (%T)
    last access time as seconds since the Unix Epoch (%X)
    last modification as seconds since the Unix Epoch (%Y)
    last change as seconds since the Unix Epoch (%Z)
    I/O block size (%o)
    */
    //stbuf->st_dev = atoi(output_chunk[1].c_str());     /* ID of device containing file */
    stbuf->st_ino = atoi(output_chunk[7].c_str());     /* inode number */
    unsigned int raw_mode;
    xtoi(output_chunk[3].c_str(),&raw_mode);
    stbuf->st_mode = raw_mode;    /* protection */
    stbuf->st_nlink = 1;   /* number of hard links */
    stbuf->st_uid = atoi(output_chunk[4].c_str());     /* user ID of owner */
    stbuf->st_gid = atoi(output_chunk[5].c_str());     /* group ID of owner */

    unsigned int device_id;
    xtoi(output_chunk[6].c_str(),&device_id);
    stbuf->st_rdev = device_id;    // device ID (if special file)

    stbuf->st_size = atoi(output_chunk[1].c_str());    /* total size, in bytes */
    stbuf->st_blksize = atoi(output_chunk[14].c_str()); /* blocksize for filesystem I/O */
    stbuf->st_blocks = atoi(output_chunk[2].c_str());  /* number of blocks allocated */
    stbuf->st_atime = atol(output_chunk[11].c_str());   /* time of last access */
    stbuf->st_mtime = atol(output_chunk[12].c_str());   /* time of last modification */
    stbuf->st_ctime = atol(output_chunk[13].c_str());   /* time of last status change */

    return res;
}

static int adb_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
			 off_t offset, struct fuse_file_info *fi)
{
	(void) offset;
	(void) fi;
    string path_string;
    path_string.assign(path);
    string_replacer(path_string," ","\\ ");

    queue<string> output;
    string command = "ls -1a \"";
    command.append(path_string);
    command.append("\"");
    output = adb_shell(command);

    while (output.size() > 0){
        filler(buf, output.front().c_str(), NULL, 0);
        output.pop();
    }

	return 0;
}

static int adb_open(const char *path, struct fuse_file_info *fi)
{
    string path_string;
    string local_path_string;
    path_string.assign(path);
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path_string);
    string_replacer(local_path_string," ","\\ ");

    queue<string> output;
    string command = "stat -t \"";
    command.append(path_string);
    command.append("\"");
    cout << command<<"\n";
    output = adb_shell(command);
    vector<string> output_chunk = make_array(output.front());
    if (output_chunk.size() < 13){
        return -ENOENT;
    }

    adb_pull(path_string,local_path_string);

    return 0;
}

static int adb_read(const char *path, char *buf, size_t size, off_t offset,
                      struct fuse_file_info *fi)
{
    int fd;
    int res;
    string local_path_string;
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path);

    fd = open(local_path_string.c_str(), O_RDONLY);

    if(fd == -1)
        return -errno;

    res = pread(fd, buf, size, offset);
        if(res == -1)
            res = -errno;

    return size;
}

static int adb_access(const char *path, int mask) {
    //###cout << "###access[path=" << path << "]" <<  endl;
    return 0;
}

static struct fuse_operations adbfs_oper;

int main(int argc, char *argv[])
{
    memset(&adbfs_oper, sizeof(adbfs_oper), 0);
    adbfs_oper.readdir= adb_readdir;
    adbfs_oper.getattr= adb_getattr;
    adbfs_oper.access= adb_access;
    adbfs_oper.open= adb_open;
    adbfs_oper.read= adb_read;
	return fuse_main(argc, argv, &adbfs_oper, NULL);
}
<commit_msg>added Write support, truncate support. TODO: delete file, mkdir, rmdir<commit_after>#define FUSE_USE_VERSION 26
#include "utils.h"

using namespace std;

queue<string> adb_push(string, string);
queue<string> adb_pull(string, string);
queue<string> adb_shell(string);
queue<string> shell(string);
map<string,fileCache> fileData;
map<string,bool> filePendingWrite;
map<string,bool> fileTruncated;

queue<string> shell(string command)
{
    string actual_command;
    string_replacer(command,"\\","\\\\");
    string_replacer(command,"'","\\'");
    string_replacer(command,"`","\\`");
    actual_command.append(command);

    return exec_command(actual_command);
}

queue<string> adb_shell(string command)
{
    string actual_command;
    string_replacer(command,"\\","\\\\");
    string_replacer(command,"'","\\'");
    string_replacer(command,"`","\\`");
    actual_command = "adb shell ";
    actual_command.append(command);
    //actual_command.append("'");

    return exec_command(actual_command);
}

queue<string> adb_pull(string remote_source, string local_destination)
{
    string actual_command;
    string_replacer(remote_source,"\\","\\\\");
    string_replacer(remote_source,"'","\\'");
    string_replacer(remote_source,"`","\\`");
    string_replacer(local_destination,"\\","\\\\");
    string_replacer(local_destination,"'","\\'");
    string_replacer(local_destination,"`","\\`");
    actual_command = "adb pull '";
    actual_command.append(remote_source);
    actual_command.append("' '");
    actual_command.append(local_destination);
    actual_command.append("'");

    return exec_command(actual_command);
}

queue<string> adb_push(string local_source, string remote_destination)
{
    string actual_command;
    string_replacer(remote_destination,"\\","\\\\");
    string_replacer(remote_destination,"'","\\'");
    string_replacer(remote_destination,"`","\\`");
    string_replacer(local_source,"\\","\\\\");
    string_replacer(local_source,"'","\\'");
    string_replacer(local_source,"`","\\`");
    actual_command = "adb push '";
    actual_command.append(local_source);
    actual_command.append("' '");
    actual_command.append(remote_destination);
    actual_command.append("'");

    return exec_command(actual_command);
}

static int adb_getattr(const char *path, struct stat *stbuf)
{
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));
    queue<string> output;
    string path_string;
    path_string.assign(path);
    string_replacer(path_string," ","\\ ");

    if (true || fileData.find(path_string) ==  fileData.end() || fileData[path_string].timestamp + 30 > time(NULL)){
        string command = "stat -t \"";
        command.append(path_string);
        command.append("\"");
        cout << command<<"\n";
        output = adb_shell(command);
        fileData[path_string].statOutput = output;
        fileData[path_string].timestamp = time(NULL);
    }else{
        output = fileData[path_string].statOutput;
        cout << "from cache " << output.front() <<"\n";
    }
    vector<string> output_chunk = make_array(output.front());
    if (output_chunk.size() < 13){
        return -ENOENT;
    }
    while (output_chunk.size() > 15){
        output_chunk.erase( output_chunk.begin());
    }
    /*
    stat -t Explained:
    file name (%n)
    total size (%s)
    number of blocks (%b)
    raw mode in hex (%f)
    UID of owner (%u)
    GID of file (%g)
    device number in hex (%D)
    inode number (%i)
    number of hard links (%h)
    major devide type in hex (%t)
    minor device type in hex (%T)
    last access time as seconds since the Unix Epoch (%X)
    last modification as seconds since the Unix Epoch (%Y)
    last change as seconds since the Unix Epoch (%Z)
    I/O block size (%o)
    */
    //stbuf->st_dev = atoi(output_chunk[1].c_str());     /* ID of device containing file */
    stbuf->st_ino = atoi(output_chunk[7].c_str());     /* inode number */
    unsigned int raw_mode;
    xtoi(output_chunk[3].c_str(),&raw_mode);
    stbuf->st_mode = raw_mode | 0700;    /* protection */
    stbuf->st_nlink = 1;   /* number of hard links */
    stbuf->st_uid = atoi(output_chunk[4].c_str());     /* user ID of owner */
    stbuf->st_gid = atoi(output_chunk[5].c_str());     /* group ID of owner */

    unsigned int device_id;
    xtoi(output_chunk[6].c_str(),&device_id);
    stbuf->st_rdev = device_id;    // device ID (if special file)

    stbuf->st_size = atoi(output_chunk[1].c_str());    /* total size, in bytes */
    stbuf->st_blksize = atoi(output_chunk[14].c_str()); /* blocksize for filesystem I/O */
    stbuf->st_blocks = atoi(output_chunk[2].c_str());  /* number of blocks allocated */
    stbuf->st_atime = atol(output_chunk[11].c_str());   /* time of last access */
    stbuf->st_mtime = atol(output_chunk[12].c_str());   /* time of last modification */
    stbuf->st_ctime = atol(output_chunk[13].c_str());   /* time of last status change */

    return res;
}

static int adb_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
			 off_t offset, struct fuse_file_info *fi)
{
	(void) offset;
	(void) fi;
    string path_string;
    path_string.assign(path);
    string_replacer(path_string," ","\\ ");

    queue<string> output;
    string command = "ls -1a \"";
    command.append(path_string);
    command.append("\"");
    output = adb_shell(command);

    while (output.size() > 0){
        filler(buf, output.front().c_str(), NULL, 0);
        output.pop();
    }

	return 0;
}

static int adb_open(const char *path, struct fuse_file_info *fi)
{
    string path_string;
    string local_path_string;
    path_string.assign(path);
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path_string);
    //string_replacer(local_path_string," ","\\ ");
    if (!fileTruncated[path_string]){
        queue<string> output;
        string command = "stat -t \"";
        command.append(path_string);
        command.append("\"");
        cout << command<<"\n";
        output = adb_shell(command);
        vector<string> output_chunk = make_array(output.front());
        if (output_chunk.size() < 13){
            return -ENOENT;
        }

        adb_pull(path_string,local_path_string);
    }else{
        fileTruncated[path_string] = false;
    }

    fi->fh = open(local_path_string.c_str(), fi->flags);

    return 0;
}

static int adb_read(const char *path, char *buf, size_t size, off_t offset,
                      struct fuse_file_info *fi)
{
    int fd;
    int res;
    fd = fi->fh; //open(local_path_string.c_str(), O_RDWR);
    if(fd == -1)
        return -errno;
    res = pread(fd, buf, size, offset);
    //close(fd);
    if(res == -1)
        res = -errno;

    return size;
}

static int adb_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
    string path_string;
    string local_path_string;
    path_string.assign(path);
    filePendingWrite[path_string] = true;
    //local_path_string.assign("/tmp/adbfs");
    //local_path_string.append(path_string);
    //string_replacer(local_path_string," ","\\ ");

    int fd = fi->fh; //open(local_path_string.c_str(), O_CREAT|O_RDWR|O_TRUNC);
    int res = pwrite(fd, buf, size, offset);
    //close(fd);
    //adb_push(local_path_string,path_string);
	//adb_shell("sync");
    if (res == -1)
		res = -errno;
    return res;
}

static int adb_flush(const char *path, struct fuse_file_info *fi) {
    string path_string;
    string local_path_string;
    path_string.assign(path);
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path_string);
	int flags = fi->flags;
    cout << "flag is: "<< flags <<"\n";
	if (filePendingWrite[path_string]) {
        filePendingWrite[path_string] = false;
        adb_push(local_path_string,path_string);
        adb_shell("sync");
	}
	return 0;
}

static int adb_release(const char *path, struct fuse_file_info *fi) {
	int fd = fi->fh;
	close(fd);
	return 0;
}

static int adb_access(const char *path, int mask) {
    //###cout << "###access[path=" << path << "]" <<  endl;
    return 0;
}

static int adb_utimens(const char *path, const struct timespec ts[2]) {
    string path_string;
    string local_path_string;
    path_string.assign(path);
    fileData[path_string].timestamp = fileData[path_string].timestamp + 50;
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path_string);

    queue<string> output;
    string command = "touch \"";
    command.append(path_string);
    command.append("\"");
    cout << command<<"\n";
    adb_shell(command);

    return 0;
}

static int adb_truncate(const char *path, off_t size) {
    string path_string;
    string local_path_string;
    path_string.assign(path);
    fileData[path_string].timestamp = fileData[path_string].timestamp + 50;
    local_path_string.assign("/tmp/adbfs");
    local_path_string.append(path_string);

    queue<string> output;
    string command = "stat -t \"";
    command.append(path_string);
    command.append("\"");
    cout << command<<"\n";
    output = adb_shell(command);
    vector<string> output_chunk = make_array(output.front());
    if (output_chunk.size() < 13){
        adb_pull(path_string,local_path_string);
    }

    fileTruncated[path_string] = true;

    cout << "truncate[path=" << local_path_string << "][size=" << size << "]" << endl;

	return truncate64(local_path_string.c_str(),size);
}

static struct fuse_operations adbfs_oper;

int main(int argc, char *argv[])
{
    memset(&adbfs_oper, sizeof(adbfs_oper), 0);
    adbfs_oper.readdir= adb_readdir;
    adbfs_oper.getattr= adb_getattr;
    adbfs_oper.access= adb_access;
    adbfs_oper.open= adb_open;
    adbfs_oper.open= adb_open;
    adbfs_oper.flush = adb_flush;
    adbfs_oper.release = adb_release;
    adbfs_oper.read= adb_read;
    adbfs_oper.write = adb_write;
    adbfs_oper.utimens = adb_utimens;
    adbfs_oper.truncate = adb_truncate;
	return fuse_main(argc, argv, &adbfs_oper, NULL);
}
<|endoftext|>


<commit_before>// GreedyMarketTests.cpp
#include <gtest/gtest.h>

#include "GreedyMarket.h"
#include "CycException.h"
#include "Message.h"
#include "MarketModelTests.h"
#include "GenericResource.h"
#include "ModelTests.h"

#include <string>
#include <queue>

using namespace std;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class FakeGreedyMarket : public GreedyMarket {
  protected:
    msg_ptr msg_;

  public:
    FakeGreedyMarket() : GreedyMarket() {
      string kg = "kg";
      string qual = "qual";
      gen_rsrc_ptr res = gen_rsrc_ptr(new GenericResource(kg, qual, 1));
      msg_ = msg_ptr(new Message(this));
      msg_->setResource(res);
    }

    virtual ~FakeGreedyMarket() {
    }

    msg_ptr getMessage(){return msg_;}
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Model* GreedyMarketModelConstructor(){
  return dynamic_cast<Model*>(new FakeGreedyMarket());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MarketModel* GreedyMarketConstructor(){
  return dynamic_cast<MarketModel*>(new FakeGreedyMarket());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class GreedyMarketTest : public ::testing::Test {
  protected:
    FakeGreedyMarket* src_market;
    FakeGreedyMarket* new_market;

    virtual void SetUp(){
      src_market = new FakeGreedyMarket();
      new_market = new FakeGreedyMarket();
    };

    virtual void TearDown() {
      delete src_market;
    }
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, InitialState) {
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, CopyMarket) {
  new_market->copy(src_market);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, CopyFreshModel) {
  new_market->copyFreshModel(dynamic_cast<Model*>(src_market)); // deep copy
  EXPECT_NO_THROW(dynamic_cast<GreedyMarket*>(new_market)); // still a source market
  EXPECT_NO_THROW(dynamic_cast<FakeGreedyMarket*>(new_market)); // still a fake source market
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, Print) {
  EXPECT_NO_THROW(src_market->print());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, ReceiveMessage) {
  EXPECT_NO_THROW(src_market->receiveMessage(src_market->getMessage()));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
INSTANTIATE_TEST_CASE_P(GreedyMarket, MarketModelTests, Values(&GreedyMarketConstructor));
INSTANTIATE_TEST_CASE_P(GreedyMarket, ModelTests, Values(&GreedyMarketModelConstructor));

<commit_msg>added Tests that check proper splitting behavior of GreedyMarket.<commit_after>// GreedyMarketTests.cpp
#include <gtest/gtest.h>

#include "GreedyMarket.h"
#include "CycException.h"
#include "Message.h"
#include "MarketModelTests.h"
#include "GenericResource.h"
#include "ModelTests.h"
#include "IsoVector.h"
#include "Material.h"
#include "FacilityModel.h"

#include <string>
#include <queue>

using namespace std;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class FakeGreedyMarket : public GreedyMarket {
  protected:
    msg_ptr msg_;

  public:
    FakeGreedyMarket() : GreedyMarket() {
      string kg = "kg";
      string qual = "qual";
      gen_rsrc_ptr res = gen_rsrc_ptr(new GenericResource(kg, qual, 1));
      msg_ = msg_ptr(new Message(this));
      msg_->setResource(res);
    }

    virtual ~FakeGreedyMarket() {
    }

    msg_ptr getMessage(){return msg_;}
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Model* GreedyMarketModelConstructor(){
  return dynamic_cast<Model*>(new FakeGreedyMarket());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MarketModel* GreedyMarketConstructor(){
  return dynamic_cast<MarketModel*>(new FakeGreedyMarket());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class FakeFacility: public FacilityModel {

public:

  std::vector<rsrc_ptr> received;
  std::vector<rsrc_ptr> sent;

  void copyFreshModel(Model* model) { };

  void receiveMessage(msg_ptr msg) {
    msg->approveTransfer();
  }

  void addResource(msg_ptr msg, vector<rsrc_ptr> manifest) {
    for (int i = 0; i < manifest.size(); i++) {
      received.push_back(manifest.at(i));
    }
  }

  std::vector<rsrc_ptr> removeResource(msg_ptr msg) {
    sent.push_back(msg->resource());
    std::vector<rsrc_ptr> manifest;
    manifest.push_back(msg->resource());
    return manifest;
  }
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class GreedyMarketTest : public ::testing::Test {
  protected:
    FakeGreedyMarket* src_market;
    FakeGreedyMarket* new_market;

    IsoVector recipe;
    Transaction trans;
    msg_ptr offer, request;
    FakeFacility* supplier;
    FakeFacility* requester;

    virtual void SetUp(){
      recipe.setMass(92235, 10);
      recipe.setMass(92238, 90);

      trans.commod = "none";
      trans.minfrac = 0.1;
      trans.price = 3;

      src_market = new FakeGreedyMarket();
      new_market = new FakeGreedyMarket();

      Communicator* recipient = dynamic_cast<Communicator*>(src_market);

      supplier = new FakeFacility();
      requester = new FakeFacility();

      trans.is_offer = false;
      request = msg_ptr(new Message(requester, recipient, trans));
      request->setNextDest(recipient);

      trans.is_offer = true;
      offer = msg_ptr(new Message(supplier, recipient, trans));
      offer->setNextDest(recipient);

    };

    virtual void TearDown() {
      delete src_market;
      delete new_market;
    }
};

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, RequestIsLarger) {
  recipe.setMass(20);
  rsrc_ptr resource(new Material(recipe));
  request->setResource(resource);

  recipe.setMass(15);
  resource = rsrc_ptr(new Material(recipe));
  offer->setResource(resource);

  request->sendOn();
  offer->sendOn();
  src_market->resolve();

  EXPECT_EQ(supplier->received.size(), 0);
  EXPECT_EQ(supplier->sent.size(), 0);
  EXPECT_EQ(requester->received.size(), 0);
  EXPECT_EQ(requester->sent.size(), 0);

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, OfferIsLarger) {
  recipe.setMass(15);
  rsrc_ptr resource(new Material(recipe));
  request->setResource(resource);

  recipe.setMass(20);
  resource = rsrc_ptr(new Material(recipe));
  offer->setResource(resource);

  request->sendOn();
  offer->sendOn();
  src_market->resolve();

  EXPECT_EQ(supplier->received.size(), 0);
  EXPECT_EQ(supplier->sent.size(), 1);
  EXPECT_EQ(requester->received.size(), 1);
  EXPECT_EQ(requester->sent.size(), 0);

}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, RequestEqOffer) {
  rsrc_ptr resource(new Material(recipe));
  request->setResource(resource);
  offer->setResource(resource);

  request->sendOn();
  offer->sendOn();
  src_market->resolve();

  EXPECT_EQ(supplier->received.size(), 0);
  EXPECT_EQ(supplier->sent.size(), 1);
  EXPECT_EQ(requester->received.size(), 1);
  EXPECT_EQ(requester->sent.size(), 0);

}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, InitialState) {
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, CopyMarket) {
  new_market->copy(src_market);
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, CopyFreshModel) {
  new_market->copyFreshModel(dynamic_cast<Model*>(src_market)); // deep copy
  EXPECT_NO_THROW(dynamic_cast<GreedyMarket*>(new_market)); // still a source market
  EXPECT_NO_THROW(dynamic_cast<FakeGreedyMarket*>(new_market)); // still a fake source market
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, Print) {
  EXPECT_NO_THROW(src_market->print());
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST_F(GreedyMarketTest, ReceiveMessage) {
  EXPECT_NO_THROW(src_market->receiveMessage(src_market->getMessage()));
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
INSTANTIATE_TEST_CASE_P(GreedyMarket, MarketModelTests, Values(&GreedyMarketConstructor));
INSTANTIATE_TEST_CASE_P(GreedyMarket, ModelTests, Values(&GreedyMarketModelConstructor));

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSceneSpatialObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

/** This is a test file for the itkSceneSpatialObject class. */
#include "itkSceneSpatialObject.h"
#include "itkEllipseSpatialObject.h"
#include "itkGroupSpatialObject.h"

int itkSceneSpatialObjectTest(int, char* [])
{
  // Create the SceneSpatialObject
  typedef itk::SceneSpatialObject<3>  SceneSpatialObjectType;
  SceneSpatialObjectType::Pointer SceneSpatialObject = SceneSpatialObjectType::New();

  // Create two ellipses to put in the SceneSpatialObject
  typedef itk::EllipseSpatialObject<3>   EllipseType;
  EllipseType::Pointer ellipse1 = EllipseType::New();
  EllipseType::Pointer ellipse2 = EllipseType::New();

  SceneSpatialObject->AddSpatialObject(ellipse1);
  SceneSpatialObject->AddSpatialObject(ellipse2);

  if(SceneSpatialObject->GetNumberOfObjects() !=2 )
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "[PASSED]" << std::endl;

  SceneSpatialObject->GetMTime(); // coverage
  std::cout << SceneSpatialObject << std::endl;

  // Test spatial objects for coverage
  typedef itk::GroupSpatialObject<3> SpatialObjectType;
  SpatialObjectType::Pointer object = SpatialObjectType::New();

  std::cout << "Testing Typename: ";
  if(strcmp(object->GetTypeName(),"GroupSpatialObject"))
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  object->GetRequestedRegion();
  object->GetBufferedRegion();
  object->GetLargestPossibleRegion();
  object->SetBoundingBoxChildrenDepth(0);

  std::cout << "Testing  BoundingBoxChildren depth: ";
  if(object->GetBoundingBoxChildrenDepth() != 0)
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing BoundingBoxChildrenName: ";
  if(object->GetBoundingBoxChildrenName() != "")
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing Set/GetParentID: ";
  object->SetParentId(3);

  if(object->GetParentId() != 3)
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing Set/GetSpacing: ";
  double spacing[3];
  spacing[0] = 1;
  spacing[1] = 2;
  spacing[2] = 3;

  object->SetSpacing(spacing);
  const double* res_spacing = object->GetSpacing();
  if((res_spacing[0] != 1) ||
     (res_spacing[1] != 2) ||
     (res_spacing[2] != 3) )
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;
  std::cout << "[DONE]" << std::endl;

  return EXIT_SUCCESS;

}
<commit_msg>ENH: Added test for the Clear() function<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSceneSpatialObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif

/** This is a test file for the itkSceneSpatialObject class. */
#include "itkSceneSpatialObject.h"
#include "itkEllipseSpatialObject.h"
#include "itkGroupSpatialObject.h"

int itkSceneSpatialObjectTest(int, char* [])
{
  // Create the SceneSpatialObject
  typedef itk::SceneSpatialObject<3>  SceneSpatialObjectType;
  SceneSpatialObjectType::Pointer SceneSpatialObject = SceneSpatialObjectType::New();

  // Create two ellipses to put in the SceneSpatialObject
  typedef itk::EllipseSpatialObject<3>   EllipseType;
  EllipseType::Pointer ellipse1 = EllipseType::New();
  EllipseType::Pointer ellipse2 = EllipseType::New();

  SceneSpatialObject->AddSpatialObject(ellipse1);
  SceneSpatialObject->AddSpatialObject(ellipse2);

  if(SceneSpatialObject->GetNumberOfObjects() !=2 )
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "[PASSED]" << std::endl;

  SceneSpatialObject->GetMTime(); // coverage
  std::cout << SceneSpatialObject << std::endl;

  // Test spatial objects for coverage
  typedef itk::GroupSpatialObject<3> SpatialObjectType;
  SpatialObjectType::Pointer object = SpatialObjectType::New();

  std::cout << "Testing Typename: ";
  if(strcmp(object->GetTypeName(),"GroupSpatialObject"))
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  object->GetRequestedRegion();
  object->GetBufferedRegion();
  object->GetLargestPossibleRegion();
  object->SetBoundingBoxChildrenDepth(0);

  std::cout << "Testing  BoundingBoxChildren depth: ";
  if(object->GetBoundingBoxChildrenDepth() != 0)
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing BoundingBoxChildrenName: ";
  if(object->GetBoundingBoxChildrenName() != "")
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing Set/GetParentID: ";
  object->SetParentId(3);

  if(object->GetParentId() != 3)
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "[PASSED]" << std::endl;

  std::cout << "Testing Set/GetSpacing: ";
  double spacing[3];
  spacing[0] = 1;
  spacing[1] = 2;
  spacing[2] = 3;

  object->SetSpacing(spacing);
  const double* res_spacing = object->GetSpacing();
  if((res_spacing[0] != 1) ||
     (res_spacing[1] != 2) ||
     (res_spacing[2] != 3) )
  {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "Testing Clear(): ";
  // Testing the clear function
  SceneSpatialObject->Clear();
  if(SceneSpatialObject->GetNumberOfObjects() != 0)
    {
    std::cout << "[FAILURE]" << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "[PASSED]" << std::endl;
  std::cout << "[DONE]" << std::endl;

  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "pal_types.h"
#include "pal_utilities.h"
#include "pal_gssapi.h"

#if HAVE_GSSFW_HEADERS
#include <GSS/GSS.h>
#else
#include <gssapi/gssapi_ext.h>
#include <gssapi/gssapi_krb5.h>
#endif

#include <assert.h>
#include <string.h>

static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG, "");
static_assert(PAL_GSS_C_MUTUAL_FLAG == GSS_C_MUTUAL_FLAG, "");
static_assert(PAL_GSS_C_REPLAY_FLAG == GSS_C_REPLAY_FLAG, "");
static_assert(PAL_GSS_C_SEQUENCE_FLAG == GSS_C_SEQUENCE_FLAG, "");
static_assert(PAL_GSS_C_CONF_FLAG == GSS_C_CONF_FLAG, "");
static_assert(PAL_GSS_C_INTEG_FLAG == GSS_C_INTEG_FLAG, "");
static_assert(PAL_GSS_C_ANON_FLAG == GSS_C_ANON_FLAG, "");
static_assert(PAL_GSS_C_PROT_READY_FLAG == GSS_C_PROT_READY_FLAG, "");
static_assert(PAL_GSS_C_TRANS_FLAG == GSS_C_TRANS_FLAG, "");
static_assert(PAL_GSS_C_DCE_STYLE == GSS_C_DCE_STYLE, "");
static_assert(PAL_GSS_C_IDENTIFY_FLAG == GSS_C_IDENTIFY_FLAG, "");
static_assert(PAL_GSS_C_EXTENDED_ERROR_FLAG == GSS_C_EXTENDED_ERROR_FLAG, "");
static_assert(PAL_GSS_C_DELEG_POLICY_FLAG == GSS_C_DELEG_POLICY_FLAG, "");

static_assert(PAL_GSS_COMPLETE == GSS_S_COMPLETE, "");
static_assert(PAL_GSS_CONTINUE_NEEDED == GSS_S_CONTINUE_NEEDED, "");

#if !HAVE_GSS_SPNEGO_MECHANISM
static char gss_spnego_oid_value[] = "\x2b\x06\x01\x05\x05\x02"; // Binary representation of SPNEGO Oid (RFC 4178)
#endif

// transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer
static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, struct PAL_GssBuffer* targetBuffer)
{
    assert(gssBuffer != nullptr);
    assert(targetBuffer != nullptr);

    targetBuffer->length = gssBuffer->length;
    targetBuffer->data = static_cast<uint8_t*>(gssBuffer->value);
}

static uint32_t NetSecurityNative_AcquireCredSpNego(uint32_t* minorStatus,
                                                    GssName* desiredName,
                                                    gss_cred_usage_t credUsage,
                                                    GssCredId** outputCredHandle)
{
    assert(minorStatus != nullptr);
    assert(desiredName != nullptr);
    assert(outputCredHandle != nullptr);

#if HAVE_GSS_SPNEGO_MECHANISM
    gss_OID_set_desc gss_mech_spnego_OID_set_desc = {.count = 1, .elements = GSS_SPNEGO_MECHANISM};
#else
    gss_OID_desc gss_mech_spnego_OID_desc = {.length = 6, .elements = static_cast<void*>(gss_spnego_oid_value)};
    gss_OID_set_desc gss_mech_spnego_OID_set_desc = {.count = 1, .elements = &gss_mech_spnego_OID_desc};
#endif
    return gss_acquire_cred(
        minorStatus, desiredName, 0, &gss_mech_spnego_OID_set_desc, credUsage, outputCredHandle, nullptr, nullptr);
}

extern "C" uint32_t
NetSecurityNative_InitiateCredSpNego(uint32_t* minorStatus, GssName* desiredName, GssCredId** outputCredHandle)
{
    return NetSecurityNative_AcquireCredSpNego(minorStatus, desiredName, GSS_C_INITIATE, outputCredHandle);
}

extern "C" uint32_t NetSecurityNative_DeleteSecContext(uint32_t* minorStatus, GssCtxId** contextHandle)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);

    return gss_delete_sec_context(minorStatus, contextHandle, GSS_C_NO_BUFFER);
}

static uint32_t NetSecurityNative_DisplayStatus(uint32_t* minorStatus,
                                                uint32_t statusValue,
                                                int statusType,
                                                struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(outBuffer != nullptr);

    uint32_t messageContext;
    GssBuffer gssBuffer{.length = 0, .value = nullptr};
    uint32_t majorStatus =
        gss_display_status(minorStatus, statusValue, statusType, GSS_C_NO_OID, &messageContext, &gssBuffer);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_DisplayMinorStatus(uint32_t* minorStatus,
                                                         uint32_t statusValue,
                                                         struct PAL_GssBuffer* outBuffer)
{
    return NetSecurityNative_DisplayStatus(minorStatus, statusValue, GSS_C_MECH_CODE, outBuffer);
}

extern "C" uint32_t NetSecurityNative_DisplayMajorStatus(uint32_t* minorStatus,
                                                         uint32_t statusValue,
                                                         struct PAL_GssBuffer* outBuffer)
{
    return NetSecurityNative_DisplayStatus(minorStatus, statusValue, GSS_C_GSS_CODE, outBuffer);
}

extern "C" uint32_t
NetSecurityNative_ImportUserName(uint32_t* minorStatus, char* inputName, uint32_t inputNameLen, GssName** outputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);
    assert(outputName != nullptr);

    GssBuffer inputNameBuffer{.length = inputNameLen, .value = inputName};
    gss_OID nameType = const_cast<gss_OID>(GSS_C_NT_USER_NAME);
    return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
}

extern "C" uint32_t NetSecurityNative_ImportPrincipalName(uint32_t* minorStatus,
                                                          char* inputName,
                                                          uint32_t inputNameLen,
                                                          GssName** outputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);
    assert(outputName != nullptr);

    GssBuffer inputNameBuffer{.length = inputNameLen, .value = inputName};
    gss_OID nameType = const_cast<gss_OID>(GSS_KRB5_NT_PRINCIPAL_NAME);
    return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
}

extern "C" uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
                                                     GssCredId* claimantCredHandle,
                                                     GssCtxId** contextHandle,
                                                     uint32_t isNtlm,
                                                     GssName* targetName,
                                                     uint32_t reqFlags,
                                                     uint8_t* inputBytes,
                                                     uint32_t inputLength,
                                                     struct PAL_GssBuffer* outBuffer,
                                                     uint32_t* retFlags)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(isNtlm == 0 || isNtlm == 1);
    assert(targetName != nullptr);
    assert(inputBytes != nullptr || inputLength == 0);
    assert(outBuffer != nullptr);
    assert(retFlags != nullptr);

// Note: claimantCredHandle can be null

#if HAVE_GSS_SPNEGO_MECHANISM
    gss_OID desiredMech = isNtlm ? GSS_NTLM_MECHANISM : GSS_SPNEGO_MECHANISM;
#else
    assert(!isNtlm && "NTLM is not supported by MIT libgssapi_krb5");
    (void)isNtlm; // unused

    gss_OID_desc gss_mech_spnego_OID_desc = {.length = 6, .elements = static_cast<void*>(gss_spnego_oid_value)};
    gss_OID desiredMech = &gss_mech_spnego_OID_desc;
#endif

    GssBuffer inputToken{.length = inputLength, .value = inputBytes};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};

    uint32_t majorStatus = gss_init_sec_context(minorStatus,
                                                claimantCredHandle,
                                                contextHandle,
                                                targetName,
                                                desiredMech,
                                                reqFlags,
                                                0,
                                                GSS_C_NO_CHANNEL_BINDINGS,
                                                &inputToken,
                                                nullptr,
                                                &gssBuffer,
                                                retFlags,
                                                nullptr);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
                                                       GssCtxId** contextHandle,
                                                       uint8_t* inputBytes,
                                                       uint32_t inputLength,
                                                       struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(inputBytes != nullptr || inputLength == 0);
    assert(outBuffer != nullptr);

    GssBuffer inputToken{.length = UnsignedCast(inputLength), .value = inputBytes};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};

    uint32_t majorStatus = gss_accept_sec_context(minorStatus,
                                                  contextHandle,
                                                  GSS_C_NO_CREDENTIAL,
                                                  &inputToken,
                                                  GSS_C_NO_CHANNEL_BINDINGS,
                                                  nullptr,
                                                  nullptr,
                                                  &gssBuffer,
                                                  0,
                                                  nullptr,
                                                  nullptr);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_ReleaseCred(uint32_t* minorStatus, GssCredId** credHandle)
{
    assert(minorStatus != nullptr);
    assert(credHandle != nullptr);

    return gss_release_cred(minorStatus, credHandle);
}

extern "C" void NetSecurityNative_ReleaseGssBuffer(void* buffer, uint64_t length)
{
    assert(buffer != nullptr);

    uint32_t minorStatus;
    GssBuffer gssBuffer{.length = length, .value = buffer};
    gss_release_buffer(&minorStatus, &gssBuffer);
}

extern "C" uint32_t NetSecurityNative_ReleaseName(uint32_t* minorStatus, GssName** inputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);

    return gss_release_name(minorStatus, inputName);
}

extern "C" uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus,
                                           GssCtxId* contextHandle,
                                           int32_t isEncrypt,
                                           uint8_t* inputBytes,
                                           int32_t offset,
                                           int32_t count,
                                           struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(isEncrypt == 1 || isEncrypt == 0);
    assert(inputBytes != nullptr);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != nullptr);
    // count refers to the length of the input message. That is, number of bytes of inputBytes
    // starting at offset that need to be wrapped.

    int confState;
    GssBuffer inputMessageBuffer{.length = UnsignedCast(count), .value = inputBytes + offset};
    GssBuffer gssBuffer;
    uint32_t majorStatus =
        gss_wrap(minorStatus, contextHandle, isEncrypt, GSS_C_QOP_DEFAULT, &inputMessageBuffer, &confState, &gssBuffer);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_Unwrap(uint32_t* minorStatus,
                                             GssCtxId* contextHandle,
                                             uint8_t* inputBytes,
                                             int32_t offset,
                                             int32_t count,
                                             struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(inputBytes != nullptr);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != nullptr);

    // count refers to the length of the input message. That is, the number of bytes of inputBytes
    // starting at offset that need to be wrapped.
    GssBuffer inputMessageBuffer{.length = UnsignedCast(count), .value = inputBytes + offset};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};
    uint32_t majorStatus = gss_unwrap(minorStatus, contextHandle, &inputMessageBuffer, &gssBuffer, nullptr, nullptr);
    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

static uint32_t NetSecurityNative_AcquireCredWithPassword(uint32_t* minorStatus,
                                                          GssName* desiredName,
                                                          char* password,
                                                          uint32_t passwdLen,
                                                          gss_cred_usage_t credUsage,
                                                          GssCredId** outputCredHandle)
{
    assert(minorStatus != nullptr);
    assert(desiredName != nullptr);
    assert(password != nullptr);
    assert(outputCredHandle != nullptr);

    GssBuffer passwordBuffer{.length = passwdLen, .value = password};
    return gss_acquire_cred_with_password(
        minorStatus, desiredName, &passwordBuffer, 0, nullptr, credUsage, outputCredHandle, nullptr, nullptr);
}

extern "C" uint32_t NetSecurityNative_InitiateCredWithPassword(
    uint32_t* minorStatus, GssName* desiredName, char* password, uint32_t passwdLen, GssCredId** outputCredHandle)
{
    return NetSecurityNative_AcquireCredWithPassword(
        minorStatus, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle);
}
<commit_msg>Fix 32bit build error of System.Net.Security.Native<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "pal_types.h"
#include "pal_utilities.h"
#include "pal_gssapi.h"

#if HAVE_GSSFW_HEADERS
#include <GSS/GSS.h>
#else
#include <gssapi/gssapi_ext.h>
#include <gssapi/gssapi_krb5.h>
#endif

#include <assert.h>
#include <string.h>

static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG, "");
static_assert(PAL_GSS_C_MUTUAL_FLAG == GSS_C_MUTUAL_FLAG, "");
static_assert(PAL_GSS_C_REPLAY_FLAG == GSS_C_REPLAY_FLAG, "");
static_assert(PAL_GSS_C_SEQUENCE_FLAG == GSS_C_SEQUENCE_FLAG, "");
static_assert(PAL_GSS_C_CONF_FLAG == GSS_C_CONF_FLAG, "");
static_assert(PAL_GSS_C_INTEG_FLAG == GSS_C_INTEG_FLAG, "");
static_assert(PAL_GSS_C_ANON_FLAG == GSS_C_ANON_FLAG, "");
static_assert(PAL_GSS_C_PROT_READY_FLAG == GSS_C_PROT_READY_FLAG, "");
static_assert(PAL_GSS_C_TRANS_FLAG == GSS_C_TRANS_FLAG, "");
static_assert(PAL_GSS_C_DCE_STYLE == GSS_C_DCE_STYLE, "");
static_assert(PAL_GSS_C_IDENTIFY_FLAG == GSS_C_IDENTIFY_FLAG, "");
static_assert(PAL_GSS_C_EXTENDED_ERROR_FLAG == GSS_C_EXTENDED_ERROR_FLAG, "");
static_assert(PAL_GSS_C_DELEG_POLICY_FLAG == GSS_C_DELEG_POLICY_FLAG, "");

static_assert(PAL_GSS_COMPLETE == GSS_S_COMPLETE, "");
static_assert(PAL_GSS_CONTINUE_NEEDED == GSS_S_CONTINUE_NEEDED, "");

#if !HAVE_GSS_SPNEGO_MECHANISM
static char gss_spnego_oid_value[] = "\x2b\x06\x01\x05\x05\x02"; // Binary representation of SPNEGO Oid (RFC 4178)
#endif

// transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer
static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, struct PAL_GssBuffer* targetBuffer)
{
    assert(gssBuffer != nullptr);
    assert(targetBuffer != nullptr);

    targetBuffer->length = gssBuffer->length;
    targetBuffer->data = static_cast<uint8_t*>(gssBuffer->value);
}

static uint32_t NetSecurityNative_AcquireCredSpNego(uint32_t* minorStatus,
                                                    GssName* desiredName,
                                                    gss_cred_usage_t credUsage,
                                                    GssCredId** outputCredHandle)
{
    assert(minorStatus != nullptr);
    assert(desiredName != nullptr);
    assert(outputCredHandle != nullptr);

#if HAVE_GSS_SPNEGO_MECHANISM
    gss_OID_set_desc gss_mech_spnego_OID_set_desc = {.count = 1, .elements = GSS_SPNEGO_MECHANISM};
#else
    gss_OID_desc gss_mech_spnego_OID_desc = {.length = 6, .elements = static_cast<void*>(gss_spnego_oid_value)};
    gss_OID_set_desc gss_mech_spnego_OID_set_desc = {.count = 1, .elements = &gss_mech_spnego_OID_desc};
#endif
    return gss_acquire_cred(
        minorStatus, desiredName, 0, &gss_mech_spnego_OID_set_desc, credUsage, outputCredHandle, nullptr, nullptr);
}

extern "C" uint32_t
NetSecurityNative_InitiateCredSpNego(uint32_t* minorStatus, GssName* desiredName, GssCredId** outputCredHandle)
{
    return NetSecurityNative_AcquireCredSpNego(minorStatus, desiredName, GSS_C_INITIATE, outputCredHandle);
}

extern "C" uint32_t NetSecurityNative_DeleteSecContext(uint32_t* minorStatus, GssCtxId** contextHandle)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);

    return gss_delete_sec_context(minorStatus, contextHandle, GSS_C_NO_BUFFER);
}

static uint32_t NetSecurityNative_DisplayStatus(uint32_t* minorStatus,
                                                uint32_t statusValue,
                                                int statusType,
                                                struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(outBuffer != nullptr);

    uint32_t messageContext;
    GssBuffer gssBuffer{.length = 0, .value = nullptr};
    uint32_t majorStatus =
        gss_display_status(minorStatus, statusValue, statusType, GSS_C_NO_OID, &messageContext, &gssBuffer);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_DisplayMinorStatus(uint32_t* minorStatus,
                                                         uint32_t statusValue,
                                                         struct PAL_GssBuffer* outBuffer)
{
    return NetSecurityNative_DisplayStatus(minorStatus, statusValue, GSS_C_MECH_CODE, outBuffer);
}

extern "C" uint32_t NetSecurityNative_DisplayMajorStatus(uint32_t* minorStatus,
                                                         uint32_t statusValue,
                                                         struct PAL_GssBuffer* outBuffer)
{
    return NetSecurityNative_DisplayStatus(minorStatus, statusValue, GSS_C_GSS_CODE, outBuffer);
}

extern "C" uint32_t
NetSecurityNative_ImportUserName(uint32_t* minorStatus, char* inputName, uint32_t inputNameLen, GssName** outputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);
    assert(outputName != nullptr);

    GssBuffer inputNameBuffer{.length = inputNameLen, .value = inputName};
    gss_OID nameType = const_cast<gss_OID>(GSS_C_NT_USER_NAME);
    return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
}

extern "C" uint32_t NetSecurityNative_ImportPrincipalName(uint32_t* minorStatus,
                                                          char* inputName,
                                                          uint32_t inputNameLen,
                                                          GssName** outputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);
    assert(outputName != nullptr);

    GssBuffer inputNameBuffer{.length = inputNameLen, .value = inputName};
    gss_OID nameType = const_cast<gss_OID>(GSS_KRB5_NT_PRINCIPAL_NAME);
    return gss_import_name(minorStatus, &inputNameBuffer, nameType, outputName);
}

extern "C" uint32_t NetSecurityNative_InitSecContext(uint32_t* minorStatus,
                                                     GssCredId* claimantCredHandle,
                                                     GssCtxId** contextHandle,
                                                     uint32_t isNtlm,
                                                     GssName* targetName,
                                                     uint32_t reqFlags,
                                                     uint8_t* inputBytes,
                                                     uint32_t inputLength,
                                                     struct PAL_GssBuffer* outBuffer,
                                                     uint32_t* retFlags)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(isNtlm == 0 || isNtlm == 1);
    assert(targetName != nullptr);
    assert(inputBytes != nullptr || inputLength == 0);
    assert(outBuffer != nullptr);
    assert(retFlags != nullptr);

// Note: claimantCredHandle can be null

#if HAVE_GSS_SPNEGO_MECHANISM
    gss_OID desiredMech = isNtlm ? GSS_NTLM_MECHANISM : GSS_SPNEGO_MECHANISM;
#else
    assert(!isNtlm && "NTLM is not supported by MIT libgssapi_krb5");
    (void)isNtlm; // unused

    gss_OID_desc gss_mech_spnego_OID_desc = {.length = 6, .elements = static_cast<void*>(gss_spnego_oid_value)};
    gss_OID desiredMech = &gss_mech_spnego_OID_desc;
#endif

    GssBuffer inputToken{.length = inputLength, .value = inputBytes};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};

    uint32_t majorStatus = gss_init_sec_context(minorStatus,
                                                claimantCredHandle,
                                                contextHandle,
                                                targetName,
                                                desiredMech,
                                                reqFlags,
                                                0,
                                                GSS_C_NO_CHANNEL_BINDINGS,
                                                &inputToken,
                                                nullptr,
                                                &gssBuffer,
                                                retFlags,
                                                nullptr);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_AcceptSecContext(uint32_t* minorStatus,
                                                       GssCtxId** contextHandle,
                                                       uint8_t* inputBytes,
                                                       uint32_t inputLength,
                                                       struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(inputBytes != nullptr || inputLength == 0);
    assert(outBuffer != nullptr);

    GssBuffer inputToken{.length = UnsignedCast(inputLength), .value = inputBytes};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};

    uint32_t majorStatus = gss_accept_sec_context(minorStatus,
                                                  contextHandle,
                                                  GSS_C_NO_CREDENTIAL,
                                                  &inputToken,
                                                  GSS_C_NO_CHANNEL_BINDINGS,
                                                  nullptr,
                                                  nullptr,
                                                  &gssBuffer,
                                                  0,
                                                  nullptr,
                                                  nullptr);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_ReleaseCred(uint32_t* minorStatus, GssCredId** credHandle)
{
    assert(minorStatus != nullptr);
    assert(credHandle != nullptr);

    return gss_release_cred(minorStatus, credHandle);
}

extern "C" void NetSecurityNative_ReleaseGssBuffer(void* buffer, uint64_t length)
{
    assert(buffer != nullptr);

    uint32_t minorStatus;
    GssBuffer gssBuffer{.length = static_cast<size_t>(length), .value = buffer};
    gss_release_buffer(&minorStatus, &gssBuffer);
}

extern "C" uint32_t NetSecurityNative_ReleaseName(uint32_t* minorStatus, GssName** inputName)
{
    assert(minorStatus != nullptr);
    assert(inputName != nullptr);

    return gss_release_name(minorStatus, inputName);
}

extern "C" uint32_t NetSecurityNative_Wrap(uint32_t* minorStatus,
                                           GssCtxId* contextHandle,
                                           int32_t isEncrypt,
                                           uint8_t* inputBytes,
                                           int32_t offset,
                                           int32_t count,
                                           struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(isEncrypt == 1 || isEncrypt == 0);
    assert(inputBytes != nullptr);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != nullptr);
    // count refers to the length of the input message. That is, number of bytes of inputBytes
    // starting at offset that need to be wrapped.

    int confState;
    GssBuffer inputMessageBuffer{.length = UnsignedCast(count), .value = inputBytes + offset};
    GssBuffer gssBuffer;
    uint32_t majorStatus =
        gss_wrap(minorStatus, contextHandle, isEncrypt, GSS_C_QOP_DEFAULT, &inputMessageBuffer, &confState, &gssBuffer);

    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

extern "C" uint32_t NetSecurityNative_Unwrap(uint32_t* minorStatus,
                                             GssCtxId* contextHandle,
                                             uint8_t* inputBytes,
                                             int32_t offset,
                                             int32_t count,
                                             struct PAL_GssBuffer* outBuffer)
{
    assert(minorStatus != nullptr);
    assert(contextHandle != nullptr);
    assert(inputBytes != nullptr);
    assert(offset >= 0);
    assert(count >= 0);
    assert(outBuffer != nullptr);

    // count refers to the length of the input message. That is, the number of bytes of inputBytes
    // starting at offset that need to be wrapped.
    GssBuffer inputMessageBuffer{.length = UnsignedCast(count), .value = inputBytes + offset};
    GssBuffer gssBuffer{.length = 0, .value = nullptr};
    uint32_t majorStatus = gss_unwrap(minorStatus, contextHandle, &inputMessageBuffer, &gssBuffer, nullptr, nullptr);
    NetSecurityNative_MoveBuffer(&gssBuffer, outBuffer);
    return majorStatus;
}

static uint32_t NetSecurityNative_AcquireCredWithPassword(uint32_t* minorStatus,
                                                          GssName* desiredName,
                                                          char* password,
                                                          uint32_t passwdLen,
                                                          gss_cred_usage_t credUsage,
                                                          GssCredId** outputCredHandle)
{
    assert(minorStatus != nullptr);
    assert(desiredName != nullptr);
    assert(password != nullptr);
    assert(outputCredHandle != nullptr);

    GssBuffer passwordBuffer{.length = passwdLen, .value = password};
    return gss_acquire_cred_with_password(
        minorStatus, desiredName, &passwordBuffer, 0, nullptr, credUsage, outputCredHandle, nullptr, nullptr);
}

extern "C" uint32_t NetSecurityNative_InitiateCredWithPassword(
    uint32_t* minorStatus, GssName* desiredName, char* password, uint32_t passwdLen, GssCredId** outputCredHandle)
{
    return NetSecurityNative_AcquireCredWithPassword(
        minorStatus, desiredName, password, passwdLen, GSS_C_INITIATE, outputCredHandle);
}
<|endoftext|>


<commit_before>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/version.h"

// These macros define the version number for the current version.
// NOTE these macros are used by some of the tool scripts and the build
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION     3
#define MINOR_VERSION     29
#define BUILD_NUMBER      12
#define PATCH_LEVEL       0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 1

// Define SONAME to have the build system put a specific SONAME into the
// shared library instead the generic SONAME generated from the V8 version
// number. This define is mainly used by the build system script.
#define SONAME            ""

#if IS_CANDIDATE_VERSION
#define CANDIDATE_STRING " (candidate)"
#else
#define CANDIDATE_STRING ""
#endif

#define SX(x) #x
#define S(x) SX(x)

#if PATCH_LEVEL > 0
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER) "."              \
        S(PATCH_LEVEL) CANDIDATE_STRING
#else
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER)                  \
        CANDIDATE_STRING
#endif

namespace v8 {
namespace internal {

int Version::major_ = MAJOR_VERSION;
int Version::minor_ = MINOR_VERSION;
int Version::build_ = BUILD_NUMBER;
int Version::patch_ = PATCH_LEVEL;
bool Version::candidate_ = (IS_CANDIDATE_VERSION != 0);
const char* Version::soname_ = SONAME;
const char* Version::version_string_ = VERSION_STRING;

// Calculate the V8 version string.
void Version::GetString(Vector<char> str) {
  const char* candidate = IsCandidate() ? " (candidate)" : "";
#ifdef USE_SIMULATOR
  const char* is_simulator = " SIMULATOR";
#else
  const char* is_simulator = "";
#endif  // USE_SIMULATOR
  if (GetPatch() > 0) {
    SNPrintF(str, "%d.%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate,
             is_simulator);
  } else {
    SNPrintF(str, "%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), candidate,
             is_simulator);
  }
}

// Calculate the SONAME for the V8 shared library.
void Version::GetSONAME(Vector<char> str) {
  if (soname_ == NULL || *soname_ == '\0') {
    // Generate generic SONAME if no specific SONAME is defined.
    const char* candidate = IsCandidate() ? "-candidate" : "";
    if (GetPatch() > 0) {
      SNPrintF(str, "libv8-%d.%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
    } else {
      SNPrintF(str, "libv8-%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), candidate);
    }
  } else {
    // Use specific SONAME.
    SNPrintF(str, "%s", soname_);
  }
}

} }  // namespace v8::internal
<commit_msg>[Auto-roll] Bump up version to 3.29.13.0<commit_after>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/version.h"

// These macros define the version number for the current version.
// NOTE these macros are used by some of the tool scripts and the build
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION     3
#define MINOR_VERSION     29
#define BUILD_NUMBER      13
#define PATCH_LEVEL       0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 1

// Define SONAME to have the build system put a specific SONAME into the
// shared library instead the generic SONAME generated from the V8 version
// number. This define is mainly used by the build system script.
#define SONAME            ""

#if IS_CANDIDATE_VERSION
#define CANDIDATE_STRING " (candidate)"
#else
#define CANDIDATE_STRING ""
#endif

#define SX(x) #x
#define S(x) SX(x)

#if PATCH_LEVEL > 0
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER) "."              \
        S(PATCH_LEVEL) CANDIDATE_STRING
#else
#define VERSION_STRING                                                         \
    S(MAJOR_VERSION) "." S(MINOR_VERSION) "." S(BUILD_NUMBER)                  \
        CANDIDATE_STRING
#endif

namespace v8 {
namespace internal {

int Version::major_ = MAJOR_VERSION;
int Version::minor_ = MINOR_VERSION;
int Version::build_ = BUILD_NUMBER;
int Version::patch_ = PATCH_LEVEL;
bool Version::candidate_ = (IS_CANDIDATE_VERSION != 0);
const char* Version::soname_ = SONAME;
const char* Version::version_string_ = VERSION_STRING;

// Calculate the V8 version string.
void Version::GetString(Vector<char> str) {
  const char* candidate = IsCandidate() ? " (candidate)" : "";
#ifdef USE_SIMULATOR
  const char* is_simulator = " SIMULATOR";
#else
  const char* is_simulator = "";
#endif  // USE_SIMULATOR
  if (GetPatch() > 0) {
    SNPrintF(str, "%d.%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate,
             is_simulator);
  } else {
    SNPrintF(str, "%d.%d.%d%s%s",
             GetMajor(), GetMinor(), GetBuild(), candidate,
             is_simulator);
  }
}

// Calculate the SONAME for the V8 shared library.
void Version::GetSONAME(Vector<char> str) {
  if (soname_ == NULL || *soname_ == '\0') {
    // Generate generic SONAME if no specific SONAME is defined.
    const char* candidate = IsCandidate() ? "-candidate" : "";
    if (GetPatch() > 0) {
      SNPrintF(str, "libv8-%d.%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), GetPatch(), candidate);
    } else {
      SNPrintF(str, "libv8-%d.%d.%d%s.so",
               GetMajor(), GetMinor(), GetBuild(), candidate);
    }
  } else {
    // Use specific SONAME.
    SNPrintF(str, "%s", soname_);
  }
}

} }  // namespace v8::internal
<|endoftext|>