Browse Source
[loader] Preserve nxlink argv markers
[loader] Preserve nxlink argv markers
6 changed files with 175 additions and 3 deletions
-
2src/core/CMakeLists.txt
-
1src/core/hle/kernel/k_process.cpp
-
22src/core/hle/kernel/k_process.h
-
109src/core/loader/homebrew_nxlink.cpp
-
23src/core/loader/homebrew_nxlink.h
-
21src/core/loader/nro.cpp
@ -0,0 +1,109 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
|||
#include "core/loader/homebrew_nxlink.h"
|
|||
|
|||
#include <cctype>
|
|||
|
|||
namespace Loader::HomebrewNxlink { |
|||
namespace { |
|||
|
|||
std::optional<std::string> GetLastArgvToken(std::string_view argv_string) { |
|||
while (!argv_string.empty() && argv_string.back() == '\0') { |
|||
argv_string.remove_suffix(1); |
|||
} |
|||
|
|||
std::optional<std::string_view> last_token; |
|||
bool in_token = false; |
|||
bool quoted = false; |
|||
size_t token_begin = 0; |
|||
size_t token_size = 0; |
|||
|
|||
for (size_t i = 0; i <= argv_string.size(); i++) { |
|||
const char c = i < argv_string.size() ? argv_string[i] : '\0'; |
|||
|
|||
if (!in_token) { |
|||
if (c == '\0' || std::isspace(static_cast<unsigned char>(c))) { |
|||
continue; |
|||
} |
|||
|
|||
in_token = true; |
|||
token_size = 0; |
|||
if (c == '"') { |
|||
quoted = true; |
|||
token_begin = i + 1; |
|||
} else { |
|||
quoted = false; |
|||
token_begin = i; |
|||
token_size = 1; |
|||
} |
|||
continue; |
|||
} |
|||
|
|||
const bool token_end = |
|||
quoted ? c == '"' || c == '\0' |
|||
: c == '\0' || std::isspace(static_cast<unsigned char>(c)); |
|||
if (token_end) { |
|||
if (token_size != 0) { |
|||
last_token = argv_string.substr(token_begin, token_size); |
|||
} |
|||
in_token = false; |
|||
quoted = false; |
|||
token_size = 0; |
|||
continue; |
|||
} |
|||
|
|||
token_size++; |
|||
} |
|||
|
|||
if (!last_token) { |
|||
return std::nullopt; |
|||
} |
|||
return std::string{*last_token}; |
|||
} |
|||
|
|||
void AppendArgvToken(std::string& argv_string, std::string_view token) { |
|||
while (!argv_string.empty() && argv_string.back() == '\0') { |
|||
argv_string.pop_back(); |
|||
} |
|||
if (!argv_string.empty()) { |
|||
argv_string.push_back(' '); |
|||
} |
|||
argv_string.append(token); |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
bool IsArgvMarker(std::string_view token) { |
|||
if (token.size() != ArgvMarkerSize || token.substr(8) != ArgvMarkerSuffix) { |
|||
return false; |
|||
} |
|||
|
|||
for (size_t i = 0; i < 8; i++) { |
|||
if (!std::isxdigit(static_cast<unsigned char>(token[i]))) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
std::optional<std::string> GetArgvMarker(std::string_view argv_string) { |
|||
auto last_token = GetLastArgvToken(argv_string); |
|||
if (!last_token || !IsArgvMarker(*last_token)) { |
|||
return std::nullopt; |
|||
} |
|||
return last_token; |
|||
} |
|||
|
|||
std::optional<std::string> PrepareArgv(std::string& argv_string, |
|||
std::string_view inherited_marker) { |
|||
auto marker = GetArgvMarker(argv_string); |
|||
if (!marker && IsArgvMarker(inherited_marker)) { |
|||
AppendArgvToken(argv_string, inherited_marker); |
|||
marker = std::string{inherited_marker}; |
|||
} |
|||
return marker; |
|||
} |
|||
|
|||
} // namespace Loader::HomebrewNxlink
|
|||
@ -0,0 +1,23 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include <cstddef> |
|||
#include <optional> |
|||
#include <string> |
|||
#include <string_view> |
|||
|
|||
namespace Loader::HomebrewNxlink { |
|||
|
|||
constexpr size_t ArgvMarkerSize = 16; |
|||
constexpr std::string_view ArgvMarkerSuffix = "_NXLINK_"; |
|||
|
|||
// This module handles only the libnx argv marker. Client stream handling should be an |
|||
// explicit byte-sink API; the marker alone must not imply logging. |
|||
bool IsArgvMarker(std::string_view token); |
|||
std::optional<std::string> GetArgvMarker(std::string_view argv_string); |
|||
std::optional<std::string> PrepareArgv(std::string& argv_string, |
|||
std::string_view inherited_marker); |
|||
|
|||
} // namespace Loader::HomebrewNxlink |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue