Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

[single-exe] Run from bundle on Windows #26904

Merged
merged 2 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/hosts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include_directories(inc)
if(WIN32)
add_subdirectory(corerun)
add_subdirectory(coreconsole)
add_subdirectory(corebundle)
add_subdirectory(coreshim)
else(WIN32)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
Expand Down
34 changes: 34 additions & 0 deletions src/coreclr/hosts/bundle/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
set(Bundle_Common_SOURCES
${CMAKE_CURRENT_LIST_DIR}/app_bundle.cpp
${CMAKE_CURRENT_LIST_DIR}/file_entry.cpp
${CMAKE_CURRENT_LIST_DIR}/header.cpp
${CMAKE_CURRENT_LIST_DIR}/manifest.cpp
${CMAKE_CURRENT_LIST_DIR}/marker.cpp
${CMAKE_CURRENT_LIST_DIR}/reader.cpp
${CMAKE_CURRENT_LIST_DIR}/runner.cpp
${CMAKE_CURRENT_LIST_DIR}/utils.cpp
)

set(Bundle_Windows_SOURCES
${Bundle_Common_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/pal_windows.cpp
)

set(Bundle_Unix_SOURCES
${Bundle_Common_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/pal_unix.cpp
)

set(Bundle_HEADERS
${CMAKE_CURRENT_LIST_DIR}/app_bundle.h
${CMAKE_CURRENT_LIST_DIR}/error_codes.h
${CMAKE_CURRENT_LIST_DIR}/file_entry.h
${CMAKE_CURRENT_LIST_DIR}/file_type.h
${CMAKE_CURRENT_LIST_DIR}/header.h
${CMAKE_CURRENT_LIST_DIR}/manifest.h
${CMAKE_CURRENT_LIST_DIR}/marker.h
${CMAKE_CURRENT_LIST_DIR}/pal.h
${CMAKE_CURRENT_LIST_DIR}/reader.h
${CMAKE_CURRENT_LIST_DIR}/runner.h
${CMAKE_CURRENT_LIST_DIR}/utils.h
)
34 changes: 34 additions & 0 deletions src/coreclr/hosts/bundle/app_bundle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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 "app_bundle.h"
#include "marker.h"
#include "runner.h"

using namespace bundle;

runner_t* app_bundle_t::s_runner = nullptr;

bool app_bundle_t::init(const char* exe_path)
{
if (!bundle::marker_t::is_bundle())
{
return false;
}

pal::string_t self_path;
pal::clr_palstring(exe_path, self_path);

static runner_t runner(exe_path);
s_runner = &runner;

StatusCode status = runner.process();

return status == StatusCode::Success;
}

bool app_bundle_t::probe(const char* path, int64_t* size, int64_t* offset)
{
return s_runner->probe(path, size, offset);
}
28 changes: 28 additions & 0 deletions src/coreclr/hosts/bundle/app_bundle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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.

// This class represents the bundle for the currently executing application
// It is the bundle-processing module's interface with the outside world.

#ifndef __APP_BUNDLE_H__
#define __APP_BUNDLE_H__

#include <stdint.h>

namespace bundle
{
class runner_t;

class app_bundle_t
{
public:
static bool init(const char *path);
static bool probe(const char* path, int64_t* size, int64_t* offset);

private:
static runner_t *s_runner;
};
}

#endif // __APP_BUNDLE_H__
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.

#include "file_entry.h"
#include "trace.h"
#include "error_codes.h"

using namespace bundle;
Expand All @@ -15,7 +14,7 @@ bool file_entry_t::is_valid() const
}

// Fixup a path to have current platform's directory separator.
void fixup_path_separator(pal::string_t& path)
void fixup_dir_separator(pal::string_t& path)
{
const pal::char_t bundle_dir_separator = '/';

Expand All @@ -38,13 +37,11 @@ file_entry_t file_entry_t::read(reader_t &reader)

if (!entry.is_valid())
{
trace::error(_X("Failure processing application bundle; possible file corruption."));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we remove this - the error description seems accurate still... and not having any feedback makes it much harder to diagnose issues.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trace:error() routines were no-ops, since the backing functions were not ported. Therefore, I removed the calls from the prototype, because the failure can be easily identified in the debugger (which we needed anyway, since there was no trace output).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - for prototype this is fine.

trace::error(_X("Invalid FileEntry detected."));
throw StatusCode::BundleExtractionFailure;
}

reader.read_path_string(entry.m_relative_path);
fixup_path_separator(entry.m_relative_path);
fixup_dir_separator(entry.m_relative_path);

return entry;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "header.h"
#include "reader.h"
#include "error_codes.h"
#include "trace.h"

using namespace bundle;

Expand All @@ -22,9 +21,6 @@ header_t header_t::read(reader_t& reader)

if (!fixed_header->is_valid())
{
trace::error(_X("Failure processing application bundle."));
trace::error(_X("Bundle header version compatibility check failed."));

throw StatusCode::BundleExtractionFailure;
}

Expand Down
68 changes: 68 additions & 0 deletions src/coreclr/hosts/bundle/pal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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.

#ifndef PAL_H
#define PAL_H

#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cstring>
#include <cstdarg>
#include <cstdint>
#include <cassert>

#if defined(_WIN32)
#include <windows.h>
#else // defined(_WIN32)
#include <cstdlib>
#include <unistd.h>
#include <libgen.h>
#include <mutex>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#endif // defined(_WIN32)

#if defined(_WIN32)
#define DIR_SEPARATOR '\\'
#define PATH_MAX MAX_PATH

#else // defined(_WIN32)
#define DIR_SEPARATOR '/'

#if !defined(PATH_MAX)
#define PATH_MAX 4096
#endif
#endif // defined(_WIN32)

namespace pal
{
typedef std::basic_ifstream<char> ifstream_t;
typedef std::istreambuf_iterator<ifstream_t::char_type> istreambuf_iterator_t;
typedef std::basic_istream<char> istream_t;

typedef char char_t;
typedef std::string string_t;
typedef std::stringstream stringstream_t;

inline bool clr_palstring(const char* cstr, string_t& out) { out.assign(cstr); return true; }

#if defined(_WIN32)
typedef HMODULE dll_t;
typedef FARPROC proc_t;
inline int pathcmp(const char_t* path1, const char_t* path2) { return ::_stricmp(path1, path2); }
#else // defined(_WIN32)
typedef void* dll_t;
typedef void* proc_t;
inline int pathcmp(const char_t* path1, const char_t* path2) { return ::strcmp(path1, path2); }
#endif // defined(_WIN32)

void* map_file_readonly(const string_t& path, size_t& length);
bool unmap_file(void* addr, size_t length);
}

#endif // PAL_H
42 changes: 42 additions & 0 deletions src/coreclr/hosts/bundle/pal_unix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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.h"

#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>

void* pal::map_file_readonly(const pal::string_t& path, size_t& length)
{
int fd = open(path.c_str(), O_RDONLY, (S_IRUSR | S_IRGRP | S_IROTH));
if (fd == -1)
{
return nullptr;
}

struct stat buf;
if (fstat(fd, &buf) != 0)
{
close(fd);
return nullptr;
}

length = buf.st_size;
void* address = mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, 0);

if(address == nullptr)
{
close(fd);
return nullptr;
}

close(fd);
return address;
}

bool pal::unmap_file(void* addr, size_t length)
{
return munmap(addr, length) == 0;
}
46 changes: 46 additions & 0 deletions src/coreclr/hosts/bundle/pal_windows.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.h"

void* pal::map_file_readonly(const pal::string_t& path, size_t& length)
{
HANDLE file = CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (file == INVALID_HANDLE_VALUE)
{
return nullptr;
}

LARGE_INTEGER fileSize;
if (GetFileSizeEx(file, &fileSize) == 0)
{
CloseHandle(file);
return nullptr;
}
length = (size_t)fileSize.QuadPart;

HANDLE map = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);

if (map == NULL)
{
CloseHandle(file);
return nullptr;
}

void* address = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);

if (map == NULL)
{
CloseHandle(file);
return nullptr;
}

return address;
}

bool pal::unmap_file(void* addr, size_t length)
{
return UnmapViewOfFile(addr) != 0;
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "reader.h"
#include "error_codes.h"
#include "trace.h"
#include <memory>

using namespace bundle;
Expand All @@ -17,8 +16,6 @@ const int8_t* reader_t::add_without_overflow(const int8_t* ptr, int64_t len)
// even if the actual arthmetic didn't overflow.
if (new_ptr < ptr)
{
trace::error(_X("Failure processing application bundle; possible file corruption."));
trace::error(_X("Arithmetic overflow computing bundle-bounds."));
throw StatusCode::BundleExtractionFailure;
}

Expand All @@ -29,8 +26,6 @@ void reader_t::set_offset(int64_t offset)
{
if (offset < 0 || offset >= m_bound)
{
trace::error(_X("Failure processing application bundle; possible file corruption."));
trace::error(_X("Arithmetic overflow while reading bundle."));
throw StatusCode::BundleExtractionFailure;
}

Expand All @@ -44,8 +39,6 @@ void reader_t::bounds_check(int64_t len)
// It is legal for post_read_ptr == m_bound_ptr after reading the last byte.
if (m_ptr < m_base_ptr || post_read_ptr > m_bound_ptr)
{
trace::error(_X("Failure processing application bundle; possible file corruption."));
trace::error(_X("Bounds check failed while reading the bundle."));
throw StatusCode::BundleExtractionFailure;
}
}
Expand All @@ -70,9 +63,6 @@ size_t reader_t::read_path_length()
if (second_byte & 0x80)
{
// There can be no more than two bytes in path_length
trace::error(_X("Failure processing application bundle; possible file corruption."));
trace::error(_X("Path length encoding read beyond two bytes."));

throw StatusCode::BundleExtractionFailure;
}

Expand All @@ -81,8 +71,6 @@ size_t reader_t::read_path_length()

if (length <= 0 || length > PATH_MAX)
{
trace::error(_X("Failure processing application bundle; possible file corruption."));
trace::error(_X("Path length is zero or too long."));
throw StatusCode::BundleExtractionFailure;
}

Expand All @@ -95,5 +83,5 @@ void reader_t::read_path_string(pal::string_t &str)
std::unique_ptr<uint8_t[]> buffer{ new uint8_t[size + 1] };
read(buffer.get(), size);
buffer[size] = 0; // null-terminator
pal::clr_palstring(reinterpret_cast<const char*>(buffer.get()), &str);
pal::clr_palstring(reinterpret_cast<const char*>(buffer.get()), str);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace bundle
void read(void* dest, int64_t len)
{
bounds_check(len);
memcpy(dest, m_ptr, len);
memcpy(dest, m_ptr, (size_t)len);
m_ptr += len;
}

Expand Down