blob: 0021af4b04bef16df9e52237248b076fad6b8edd [file] [log] [blame]
// Copyright 2015 The Chromium 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 <fcntl.h>
#include "base/files/file_util.h"
#include "base/logging.h"
#include "mojo/nacl/nonsfi/irt_mojo_nonsfi.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "native_client/src/untrusted/irt/irt_dev.h"
#include "services/nacl/nonsfi/pnacl_link.mojom.h"
namespace {
typedef int (*LinkerCallback)(int, const int*, int);
class PexeLinkerImpl : public mojo::nacl::PexeLinker {
public:
PexeLinkerImpl(mojo::ScopedMessagePipeHandle handle, LinkerCallback func)
: func_(func), strong_binding_(this, handle.Pass()) {}
void PexeLink(mojo::Array<mojo::String> obj_file_names,
const mojo::Callback<void(mojo::String)>& callback)
override {
// Create a temporary .nexe file which will be the result of calling our
// linker.
base::FilePath nexe_file_name;
CHECK(CreateTemporaryFile(&nexe_file_name))
<< "Could not create temporary nexe file";
int nexe_file_fd = open(nexe_file_name.value().c_str(), O_RDWR);
CHECK_GE(nexe_file_fd, 0) << "Could not create temp file for linked nexe";
// Open our temporary object file. Additionally, unlink it, since it is a
// temporary file that is no longer needed after it is opened.
size_t obj_file_fd_count = obj_file_names.size();
int obj_file_fds[obj_file_fd_count];
for (size_t i = 0; i < obj_file_fd_count; i++) {
obj_file_fds[i] = open(obj_file_names[i].get().c_str(), O_RDONLY);
CHECK(!unlink(obj_file_names[i].get().c_str()))
<< "Could not unlink temporary object file";
CHECK_GE(obj_file_fds[i], 0) << "Could not open object file";
}
CHECK(!func_(nexe_file_fd, obj_file_fds, obj_file_fd_count))
<< "Error calling func on object file";
// Return the name of the nexe file.
callback.Run(mojo::String(nexe_file_name.value()));
mojo::RunLoop::current()->Quit();
}
private:
LinkerCallback func_;
mojo::StrongBinding<mojo::nacl::PexeLinker> strong_binding_;
};
void ServeLinkRequest(LinkerCallback func) {
// Acquire the handle -- this is our mechanism to contact the
// content handler which called us.
MojoHandle handle;
nacl::MojoGetInitialHandle(&handle);
// Convert the MojoHandle into a ScopedMessagePipeHandle, and use that to
// implement the PexeLinker interface.
PexeLinkerImpl impl(
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(handle)).Pass(),
func);
mojo::RunLoop::current()->Run();
}
} // namespace anonymous
namespace nacl {
const struct nacl_irt_private_pnacl_translator_link
nacl_irt_private_pnacl_translator_link = {
ServeLinkRequest
};
} // namespace nacl