Skip to content
4 changes: 2 additions & 2 deletions src/native/clr/host/host-shared.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ auto HostCommon::get_java_class_name_for_TypeManager (jclass klass) noexcept ->
JNIEnv *env = OSBridge::ensure_jnienv ();
jstring name = reinterpret_cast<jstring> (env->CallObjectMethod (klass, Class_getName));
if (name == nullptr) {
log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at {:p}", reinterpret_cast<void*>(klass));
log_errorf (LOG_DEFAULT, "Failed to obtain Java class name for object at %p", reinterpret_cast<void*>(klass));
return nullptr;
}

const char *mutf8 = env->GetStringUTFChars (name, nullptr);
if (mutf8 == nullptr) {
log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"sv);
log_errorf (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)");
env->DeleteLocalRef (name);
return nullptr;
}
Expand Down
59 changes: 42 additions & 17 deletions src/native/clr/include/runtime-base/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ namespace xamarin::android {
{
struct stat sbuf;
if (fstatat (dirfd, file_name, &sbuf, 0) == -1) {
log_warn (LOG_ASSEMBLY, "Failed to stat file '{}': {}", file_name, std::strerror (errno));
log_warnf (LOG_ASSEMBLY, "Failed to stat file '%s': %s", optional_string (file_name), std::strerror (errno));
return std::nullopt;
}

Expand All @@ -154,18 +154,30 @@ namespace xamarin::android {
[[gnu::flatten, gnu::always_inline]]
static void set_environment_variable (const char *name, const char *value) noexcept
{
log_debug (LOG_DEFAULT, "Setting environment variable {} = '{}'", optional_string (name), optional_string (value));
log_debugf (LOG_DEFAULT, "Setting environment variable %s = '%s'", optional_string (name), optional_string (value));
if (::setenv (name, value, 1) < 0) {
log_warn (LOG_DEFAULT, "Failed to set environment variable '{}': {}", name, ::strerror (errno));
log_warnf (LOG_DEFAULT, "Failed to set environment variable '%s': %s", optional_string (name), ::strerror (errno));
}
}

[[gnu::flatten, gnu::always_inline]]
static void set_environment_variable_if_unset (std::string_view const& name, jstring_wrapper& value) noexcept
{
log_debug (LOG_DEFAULT, "Setting environment variable {} = '{}' if unset", name, value.get_string_view ());
log_debugf (
LOG_DEFAULT,
"Setting environment variable %.*s = '%s' if unset",
static_cast<int>(name.length ()),
name.data (),
optional_string (value.get_cstr ())
);
if (::setenv (name.data (), value.get_cstr (), 0) < 0) {
log_warn (LOG_DEFAULT, "Failed to set environment variable '{}': {}", name, ::strerror (errno));
log_warnf (
LOG_DEFAULT,
"Failed to set environment variable '%.*s': %s",
static_cast<int>(name.length ()),
name.data (),
::strerror (errno)
);
}
}

Expand All @@ -187,7 +199,14 @@ namespace xamarin::android {
if (createDirectory) {
int rv = create_directory (value.get_cstr (), mode);
if (rv < 0 && errno != EEXIST) {
log_warn (LOG_DEFAULT, "Failed to create directory '{}' for environment variable '{}'. {}", value.get_string_view (), name, strerror (errno));
log_warnf (
LOG_DEFAULT,
"Failed to create directory '%s' for environment variable '%.*s'. %s",
optional_string (value.get_cstr ()),
static_cast<int>(name.length ()),
name.data (),
strerror (errno)
);
}
}
set_environment_variable (name, value);
Expand Down Expand Up @@ -217,32 +236,33 @@ namespace xamarin::android {
mmap_info.area = mmap (nullptr, offsetSize, PROT_READ, MAP_PRIVATE, fd, static_cast<off_t>(offsetPage));

if (mmap_info.area == MAP_FAILED) {
Helpers::abort_application (
Helpers::abort_applicationf (
LOG_ASSEMBLY,
std::format (
"Could not mmap APK fd {}: {}; File={}",
fd,
strerror (errno),
filename
)
std::source_location::current (),
"Could not mmap APK fd %d: %s; File=%.*s",
fd,
strerror (errno),
static_cast<int>(filename.length ()),
filename.data ()
);
}

mmap_info.size = offsetSize;
file_info.area = pointer_add (mmap_info.area, offsetFromPage);
file_info.size = size;

log_info (
log_infof (
LOG_ASSEMBLY,
" mmap_start: {:<8p}; mmap_end: {:<8p} mmap_len: {:<12} file_start: {:<8p} file_end: {:<8p} file_len: {:<12} apk descriptor: {} file: {}",
" mmap_start: %p; mmap_end: %p\t mmap_len: %zu file_start: %p file_end: %p\t file_len: %zu\t apk descriptor: %d file: %.*s",
mmap_info.area,
pointer_add (mmap_info.area, mmap_info.size),
mmap_info.size,
file_info.area,
pointer_add (file_info.area, file_info.size),
file_info.size,
fd,
filename
static_cast<int>(filename.length ()),
filename.data ()
);

return file_info;
Expand All @@ -265,7 +285,12 @@ namespace xamarin::android {
elf_header->e_ident[EI_MAG1] != ELFMAG1 ||
elf_header->e_ident[EI_MAG2] != ELFMAG2 ||
elf_header->e_ident[EI_MAG3] != ELFMAG3) {
log_debug (LOG_ASSEMBLY, "Not an ELF image: {}", file_name);
log_debugf (
LOG_ASSEMBLY,
"Not an ELF image: %.*s",
static_cast<int>(file_name.length ()),
file_name.data ()
);
// Not an ELF image, just return what we mmapped before
return { map_info.area, map_info.size };
}
Expand Down
7 changes: 7 additions & 0 deletions src/native/clr/include/shared/log_types.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cstdarg>
#include <cstdint>
#include <format>
#include <string>
Expand Down Expand Up @@ -47,6 +48,12 @@ namespace xamarin::android {
// A slightly faster alternative to other log functions as it doesn't parse the message
// for format placeholders nor it uses variable arguments
void log_write (LogCategories category, LogLevel level, const char *message) noexcept;
void log_writev (LogCategories category, LogLevel level, const char *format, va_list args) noexcept;
void log_writef (LogCategories category, LogLevel level, const char *format, ...) noexcept __attribute__ ((format (printf, 3, 4)));
void log_debugf (LogCategories category, const char *format, ...) noexcept __attribute__ ((format (printf, 2, 3)));
void log_infof (LogCategories category, const char *format, ...) noexcept __attribute__ ((format (printf, 2, 3)));
void log_warnf (LogCategories category, const char *format, ...) noexcept __attribute__ ((format (printf, 2, 3)));
void log_errorf (LogCategories category, const char *format, ...) noexcept __attribute__ ((format (printf, 2, 3)));

[[gnu::always_inline]]
static inline void log_write (LogCategories category, LogLevel level, std::string_view const& message) noexcept
Expand Down
12 changes: 9 additions & 3 deletions src/native/clr/runtime-base/android-system-shared.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ AndroidSystem::monodroid__system_property_get (std::string_view const& name, cha
char *buf = nullptr;
if (sp_value_len < Constants::PROPERTY_VALUE_BUFFER_LEN) {
size_t alloc_size = Helpers::add_with_overflow_check<size_t> (Constants::PROPERTY_VALUE_BUFFER_LEN, 1uz);
log_warn (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only {} bytes", sp_value_len);
log_warnf (LOG_DEFAULT, "Buffer to store system property may be too small, will copy only %zu bytes", sp_value_len);
buf = new char [alloc_size];
}

Expand Down Expand Up @@ -81,10 +81,16 @@ AndroidSystem::get_max_gref_count_from_system () noexcept -> long
}

if (*e) {
log_warn (LOG_GC, "Unsupported '{}' value '{}'.", Constants::DEBUG_MONO_MAX_GREFC.data (), override.get ());
log_warnf (
LOG_GC,
"Unsupported '%.*s' value '%s'.",
static_cast<int>(Constants::DEBUG_MONO_MAX_GREFC.length ()),
Constants::DEBUG_MONO_MAX_GREFC.data (),
override.get ()
);
}

log_warn (LOG_GC, "Overriding max JNI Global Reference count to {}", max);
log_warnf (LOG_GC, "Overriding max JNI Global Reference count to %ld", max);
}

return max;
Expand Down
26 changes: 22 additions & 4 deletions src/native/clr/runtime-base/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ Util::create_public_directory (std::string_view const& dir)
// Try to change the mode, just in case
chmod (dir.data (), 0777);
} else {
log_warn (LOG_DEFAULT, "Failed to create directory '{}'. {}"sv, dir, std::strerror (errno));
log_warnf (
LOG_DEFAULT,
"Failed to create directory '%.*s'. %s",
static_cast<int>(dir.length ()),
dir.data (),
std::strerror (errno)
);
}
}
umask (m);
Expand All @@ -72,7 +78,13 @@ Util::monodroid_fopen (std::string_view const& filename, std::string_view const&
*/
FILE *ret = fopen (filename.data (), mode.data ());
if (ret == nullptr) {
log_error (LOG_DEFAULT, "fopen failed for file {}: {}", filename, strerror (errno));
log_errorf (
LOG_DEFAULT,
"fopen failed for file %.*s: %s",
static_cast<int>(filename.length ()),
filename.data (),
strerror (errno)
);
return nullptr;
}

Expand All @@ -87,7 +99,13 @@ void Util::set_world_accessable (std::string_view const& path)
} while (r == -1 && errno == EINTR);

if (r == -1) {
log_error (LOG_DEFAULT, "chmod(\"{}\", 0664) failed: {}", path, strerror (errno));
log_errorf (
LOG_DEFAULT,
"chmod(\"%.*s\", 0664) failed: %s",
static_cast<int>(path.length ()),
path.data (),
strerror (errno)
);
}
}

Expand All @@ -99,7 +117,7 @@ auto Util::set_world_accessible (int fd) noexcept -> bool
} while (r == -1 && errno == EINTR);

if (r == -1) {
log_error (LOG_DEFAULT, "fchmod() failed: {}"sv, strerror (errno));
log_errorf (LOG_DEFAULT, "fchmod() failed: %s", strerror (errno));
return false;
}

Expand Down
21 changes: 18 additions & 3 deletions src/native/clr/shared/helpers.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <android/set_abort_message.h>

Expand All @@ -7,11 +8,24 @@

using namespace xamarin::android;

[[noreturn]] void
Helpers::abort_applicationf (LogCategories category, std::source_location sloc, const char *format, ...) noexcept
{
char *message = nullptr;
const char *safe_format = format == nullptr ? "<null>" : format;
va_list args;
va_start (args, format);
int ret = vasprintf (&message, safe_format, args);
va_end (args);

abort_application (category, ret < 0 ? safe_format : message, true, sloc);
}

[[noreturn]] void
Helpers::abort_application (LogCategories category, const char *message, bool log_location, std::source_location sloc) noexcept
{
// Log it, but also...
log_fatal (category, "{}", message);
log_write (category, LogLevel::Fatal, message);

// ...let android include it in the tombstone, debuggerd output, stack trace etc
android_set_abort_message (message);
Expand All @@ -33,9 +47,10 @@ Helpers::abort_application (LogCategories category, const char *message, bool lo
}
}

log_fatal (
log_writef (
category,
"Abort at {}:{}:{} ('{}')",
LogLevel::Fatal,
"Abort at %s:%u:%u ('%s')",
file_name,
sloc.line (),
sloc.column (),
Expand Down
77 changes: 70 additions & 7 deletions src/native/clr/shared/log_functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ namespace {
};

constexpr size_t loglevel_map_max_index = (sizeof(loglevel_map) / sizeof(android_LogPriority)) - 1;

[[gnu::always_inline]]
auto priority_for_level (LogLevel level) noexcept -> android_LogPriority
{
size_t map_index = static_cast<size_t>(level);
if (map_index > loglevel_map_max_index) {
return DEFAULT_PRIORITY;
}

return loglevel_map[map_index];
}
}

unsigned int log_categories = LOG_NONE;
Expand Down Expand Up @@ -117,15 +128,67 @@ namespace xamarin::android {
void
log_write (LogCategories category, LogLevel level, const char *message) noexcept
{
size_t map_index = static_cast<size_t>(level);
android_LogPriority priority;
__android_log_write (priority_for_level (level), category_name (category), message);
}

if (map_index > loglevel_map_max_index) {
priority = DEFAULT_PRIORITY;
} else {
priority = loglevel_map[map_index];
void
log_writev (LogCategories category, LogLevel level, const char *format, va_list args) noexcept
{
const char *safe_format = format == nullptr ? "<null>" : format;
__android_log_vprint (priority_for_level (level), category_name (category), safe_format, args);
}

void
log_writef (LogCategories category, LogLevel level, const char *format, ...) noexcept
{
va_list args;
va_start (args, format);
log_writev (category, level, format, args);
va_end (args);
}

void
log_debugf (LogCategories category, const char *format, ...) noexcept
{
if ((log_categories & category) == 0) {
return;
}

va_list args;
va_start (args, format);
log_writev (category, LogLevel::Debug, format, args);
va_end (args);
}

void
log_infof (LogCategories category, const char *format, ...) noexcept
{
if ((log_categories & category) == 0) {
return;
}

__android_log_write (priority, category_name (category), message);
va_list args;
va_start (args, format);
log_writev (category, LogLevel::Info, format, args);
va_end (args);
}

void
log_warnf (LogCategories category, const char *format, ...) noexcept
{
va_list args;
va_start (args, format);
log_writev (category, LogLevel::Warn, format, args);
va_end (args);
}

void
log_errorf (LogCategories category, const char *format, ...) noexcept
{
va_list args;
va_start (args, format);
log_writev (category, LogLevel::Error, format, args);
va_end (args);
}

}
3 changes: 3 additions & 0 deletions src/native/common/include/shared/helpers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ namespace xamarin::android
[[noreturn]]
static void abort_application (LogCategories category, const char *message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept;

[[noreturn]]
static void abort_applicationf (LogCategories category, std::source_location sloc, const char *format, ...) noexcept __attribute__ ((format (printf, 3, 4)));

[[noreturn]]
static void abort_application (LogCategories category, std::string const& message, bool log_location = true, std::source_location sloc = std::source_location::current ()) noexcept
{
Expand Down
Loading
Loading