Improve narrow() and size32() with src_loc detection

This commit is contained in:
Nekotekina 2020-12-09 16:03:15 +03:00
parent e055d16b2c
commit 5d934c8759
16 changed files with 69 additions and 48 deletions

View File

@ -24,7 +24,7 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
const std::size_t buf_size = source.size() + 1; const std::size_t buf_size = source.size() + 1;
// Safe size // Safe size
const int size = narrow<int>(buf_size, "to_wchar" HERE); const int size = narrow<int>(buf_size);
// Buffer for max possible output length // Buffer for max possible output length
std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size + 8 + 32768]); std::unique_ptr<wchar_t[]> buffer(new wchar_t[buf_size + 8 + 32768]);
@ -55,7 +55,7 @@ static void to_utf8(std::string& out, const wchar_t* source)
const std::size_t length = std::wcslen(source); const std::size_t length = std::wcslen(source);
// Safe buffer size for max possible output length (including null terminator) // Safe buffer size for max possible output length (including null terminator)
const int buf_size = narrow<int>(length * 3 + 1, "to_utf8" HERE); const int buf_size = narrow<int>(length * 3 + 1);
// Resize buffer // Resize buffer
out.resize(buf_size - 1); out.resize(buf_size - 1);
@ -1028,7 +1028,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 read(void* buffer, u64 count) override u64 read(void* buffer, u64 count) override
{ {
// TODO (call ReadFile multiple times if count is too big) // TODO (call ReadFile multiple times if count is too big)
const int size = narrow<int>(count, "file::read" HERE); const int size = narrow<int>(count);
DWORD nread; DWORD nread;
ensure(ReadFile(m_handle, buffer, size, &nread, NULL)); // "file::read" ensure(ReadFile(m_handle, buffer, size, &nread, NULL)); // "file::read"
@ -1039,7 +1039,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
u64 write(const void* buffer, u64 count) override u64 write(const void* buffer, u64 count) override
{ {
// TODO (call WriteFile multiple times if count is too big) // TODO (call WriteFile multiple times if count is too big)
const int size = narrow<int>(count, "file::write" HERE); const int size = narrow<int>(count);
DWORD nwritten; DWORD nwritten;
ensure(WriteFile(m_handle, buffer, size, &nwritten, NULL)); // "file::write" ensure(WriteFile(m_handle, buffer, size, &nwritten, NULL)); // "file::write"

View File

@ -452,7 +452,7 @@ public:
name.append(".gz"); name.append(".gz");
z_stream zs{}; z_stream zs{};
uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize(), HERE)) + 256; uLong zsz = compressBound(::narrow<u32>(obj.getBufferSize())) + 256;
auto zbuf = std::make_unique<uchar[]>(zsz); auto zbuf = std::make_unique<uchar[]>(zsz);
#ifndef _MSC_VER #ifndef _MSC_VER
#pragma GCC diagnostic push #pragma GCC diagnostic push

View File

@ -287,7 +287,7 @@ namespace fmt
thread_ctrl::emergency_exit(out); thread_ctrl::emergency_exit(out);
} }
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg) void raw_narrow_error(const src_loc& loc, const fmt_type_info* sup, u64 arg)
{ {
std::string out{"Narrow error"}; std::string out{"Narrow error"};
@ -298,10 +298,22 @@ namespace fmt
out += ")"; out += ")";
} }
if (msg) if (loc.col != umax)
{ {
out += ": "; fmt::append(out, "\n(in file %s:%s[:%s]", loc.file, loc.line, loc.col);
out += msg; }
else
{
fmt::append(out, "\n(in file %s:%s", loc.file, loc.line);
}
if (loc.func && *loc.func)
{
fmt::append(out, ", in function %s)", loc.func);
}
else
{
out += ')';
} }
thread_ctrl::emergency_exit(out); thread_ctrl::emergency_exit(out);

View File

@ -779,7 +779,7 @@ namespace fmt
{ {
[[noreturn]] void raw_error(const char* msg); [[noreturn]] void raw_error(const char* msg);
[[noreturn]] void raw_verify_error(const src_loc& loc); [[noreturn]] void raw_verify_error(const src_loc& loc);
[[noreturn]] void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg); [[noreturn]] void raw_narrow_error(const src_loc& loc, const fmt_type_info* sup, u64 arg);
} }
template <typename T> template <typename T>
@ -870,13 +870,17 @@ struct narrow_impl<From, To, std::void_t<typename From::simple_type>>
}; };
template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))> template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
inline To narrow(const From& value, const char* msg = nullptr) [[nodiscard]] constexpr To narrow(const From& value,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION())
{ {
// Narrow check // Narrow check
if (narrow_impl<From, To>::test(value)) if (narrow_impl<From, To>::test(value)) [[unlikely]]
{ {
// Pack value as formatting argument // Pack value as formatting argument
fmt::raw_narrow_error(msg, fmt::get_type_info<fmt_unveil_t<From>>(), fmt_unveil<From>::get(value)); fmt::raw_narrow_error({line, col, file, func}, fmt::get_type_info<fmt_unveil_t<From>>(), fmt_unveil<From>::get(value));
} }
return static_cast<To>(value); return static_cast<To>(value);
@ -884,15 +888,20 @@ inline To narrow(const From& value, const char* msg = nullptr)
// Returns u32 size() for container // Returns u32 size() for container
template <typename CT, typename = decltype(static_cast<u32>(std::declval<CT>().size()))> template <typename CT, typename = decltype(static_cast<u32>(std::declval<CT>().size()))>
inline u32 size32(const CT& container, const char* msg = nullptr) [[nodiscard]] constexpr u32 size32(const CT& container,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION())
{ {
return narrow<u32>(container.size(), msg); return narrow<u32>(container.size(), line, col, file, func);
} }
// Returns u32 size for an array // Returns u32 size for an array
template <typename T, std::size_t Size> template <typename T, std::size_t Size>
constexpr u32 size32(const T (&)[Size], const char* msg = nullptr) [[nodiscard]] constexpr u32 size32(const T (&)[Size])
{ {
static_assert(Size < UINT32_MAX, "Array is too big for 32-bit");
return static_cast<u32>(Size); return static_cast<u32>(Size);
} }

View File

@ -575,7 +575,7 @@ int validate_npd_hashes(const char* file_name, const u8* klicensee, NPD_HEADER *
int title_hash_result = 0; int title_hash_result = 0;
int dev_hash_result = 0; int dev_hash_result = 0;
const s32 file_name_length = ::narrow<s32>(std::strlen(file_name), HERE); const s32 file_name_length = ::narrow<s32>(std::strlen(file_name));
const std::size_t buf_len = 0x30 + file_name_length; const std::size_t buf_len = 0x30 + file_name_length;
std::unique_ptr<u8[]> buf(new u8[buf_len]); std::unique_ptr<u8[]> buf(new u8[buf_len]);

View File

@ -745,7 +745,7 @@ bool SCEDecrypter::DecryptData()
// Calculate the total data size. // Calculate the total data size.
for (unsigned int i = 0; i < meta_hdr.section_count; i++) for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{ {
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
} }
// Allocate a buffer to store decrypted data. // Allocate a buffer to store decrypted data.
@ -799,7 +799,7 @@ bool SCEDecrypter::DecryptData()
} }
// Advance the buffer's offset. // Advance the buffer's offset.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
} }
return true; return true;
@ -829,7 +829,7 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
strm.zalloc = Z_NULL; strm.zalloc = Z_NULL;
strm.zfree = Z_NULL; strm.zfree = Z_NULL;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
strm.avail_in = ::narrow<uInt>(meta_shdr[i].data_size, HERE); strm.avail_in = ::narrow<uInt>(meta_shdr[i].data_size);
strm.avail_out = BUFSIZE; strm.avail_out = BUFSIZE;
strm.next_in = data_buf.get()+data_buf_offset; strm.next_in = data_buf.get()+data_buf_offset;
strm.next_out = tempbuf; strm.next_out = tempbuf;
@ -874,7 +874,7 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
} }
// Advance the data buffer offset by data size. // Advance the data buffer offset by data size.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
if (out_f.pos() != out_f.size()) if (out_f.pos() != out_f.size())
fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size()); fmt::throw_exception("MakeELF written bytes (%llu) does not equal buffer size (%llu).", out_f.pos(), out_f.size());
@ -1243,7 +1243,7 @@ bool SELFDecrypter::DecryptData()
if (meta_shdr[i].encrypted == 3) if (meta_shdr[i].encrypted == 3)
{ {
if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count)) if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
data_buf_length += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_length += ::narrow<u32>(meta_shdr[i].data_size);
} }
} }
@ -1289,7 +1289,7 @@ bool SELFDecrypter::DecryptData()
memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size); memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
// Advance the buffer's offset. // Advance the buffer's offset.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
} }
} }
} }

View File

@ -489,7 +489,7 @@ private:
} }
// Advance the data buffer offset by data size. // Advance the data buffer offset by data size.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size, HERE); data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
} }
} }

View File

@ -82,7 +82,7 @@ bool statichle_handler::load_patterns()
for (u32 j = 0; j < 32; j++) for (u32 j = 0; j < 32; j++)
dapat.start_pattern[j] = char_to_u8(pattern[0][j * 2], pattern[0][(j * 2) + 1]); dapat.start_pattern[j] = char_to_u8(pattern[0][j * 2], pattern[0][(j * 2) + 1]);
dapat.crc16_length = ::narrow<u8>(char_to_u8(pattern[1][0], pattern[1][1]), HERE); dapat.crc16_length = ::narrow<u8>(char_to_u8(pattern[1][0], pattern[1][1]));
dapat.crc16 = (char_to_u8(pattern[2][0], pattern[2][1]) << 8) | char_to_u8(pattern[2][2], pattern[2][3]); dapat.crc16 = (char_to_u8(pattern[2][0], pattern[2][1]) << 8) | char_to_u8(pattern[2][2], pattern[2][3]);
dapat.total_length = (char_to_u8(pattern[3][0], pattern[3][1]) << 8) | char_to_u8(pattern[3][2], pattern[3][3]); dapat.total_length = (char_to_u8(pattern[3][0], pattern[3][1]) << 8) | char_to_u8(pattern[3][2], pattern[3][3]);
dapat._module = pattern[4]; dapat._module = pattern[4];

View File

@ -798,10 +798,10 @@ error_code cellImeJpMoveFocusClause(CellImeJpHandle hImeJpHandle, s16 moveType)
manager->moveCursor(-1); manager->moveCursor(-1);
break; break;
case CELL_IMEJP_FOCUS_TOP: case CELL_IMEJP_FOCUS_TOP:
manager->moveCursor(-1 * ::narrow<s8>(manager->input_string.length(), HERE)); manager->moveCursor(-1 * ::narrow<s8>(manager->input_string.length()));
break; break;
case CELL_IMEJP_FOCUS_END: case CELL_IMEJP_FOCUS_END:
manager->moveCursor(::narrow<s8>(manager->input_string.length(), HERE)); manager->moveCursor(::narrow<s8>(manager->input_string.length()));
manager->moveCursor(-1); manager->moveCursor(-1);
break; break;
default: default:

View File

@ -2056,7 +2056,7 @@ s32 _spurs::trace_initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<
spurs->traceBuffer.set(buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0)); spurs->traceBuffer.set(buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0));
spurs->traceMode = mode; spurs->traceMode = mode;
u32 spuTraceDataCount = ::narrow<u32>((spurs->traceDataSize / sizeof(CellSpursTracePacket)) / spurs->nSpus, HERE); u32 spuTraceDataCount = ::narrow<u32>((spurs->traceDataSize / sizeof(CellSpursTracePacket)) / spurs->nSpus);
for (u32 i = 0, j = 8; i < 6; i++) for (u32 i = 0, j = 8; i < 6; i++)
{ {
spurs->traceStartIndex[i] = j; spurs->traceStartIndex[i] = j;

View File

@ -813,9 +813,9 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
{ {
if (prog.p_memsz) if (prog.p_memsz)
{ {
const u32 mem_size = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE); const u32 mem_size = ::narrow<u32>(prog.p_memsz);
const u32 file_size = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE); const u32 file_size = ::narrow<u32>(prog.p_filesz);
const u32 init_addr = ::narrow<u32>(prog.p_vaddr, "p_vaddr" HERE); const u32 init_addr = ::narrow<u32>(prog.p_vaddr);
// Alloc segment memory // Alloc segment memory
const u32 addr = vm::alloc(mem_size, vm::main); const u32 addr = vm::alloc(mem_size, vm::main);
@ -1143,11 +1143,11 @@ void ppu_load_exec(const ppu_exec_object& elf)
ppu_loader.notice("** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags); ppu_loader.notice("** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
ppu_segment _seg; ppu_segment _seg;
const u32 addr = _seg.addr = vm::cast(prog.p_vaddr, HERE); const u32 addr = _seg.addr = vm::cast(prog.p_vaddr);
const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE); const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz);
const u32 type = _seg.type = prog.p_type; const u32 type = _seg.type = prog.p_type;
const u32 flag = _seg.flags = prog.p_flags; const u32 flag = _seg.flags = prog.p_flags;
_seg.filesz = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE); _seg.filesz = ::narrow<u32>(prog.p_filesz);
// Hash big-endian values // Hash big-endian values
sha1_update(&sha, reinterpret_cast<const uchar*>(&prog.p_type), sizeof(prog.p_type)); sha1_update(&sha, reinterpret_cast<const uchar*>(&prog.p_type), sizeof(prog.p_type));
@ -1280,8 +1280,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
case 0x00000007: // TLS case 0x00000007: // TLS
{ {
tls_vaddr = vm::cast(prog.p_vaddr, HERE); tls_vaddr = vm::cast(prog.p_vaddr, HERE);
tls_fsize = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE); tls_fsize = ::narrow<u32>(prog.p_filesz);
tls_vsize = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE); tls_vsize = ::narrow<u32>(prog.p_memsz);
ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", tls_vaddr, tls_fsize, tls_vsize); ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", tls_vaddr, tls_fsize, tls_vsize);
break; break;
@ -1647,10 +1647,10 @@ std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object& elf, const
ppu_segment _seg; ppu_segment _seg;
const u32 addr = _seg.addr = vm::cast(prog.p_vaddr, HERE); const u32 addr = _seg.addr = vm::cast(prog.p_vaddr, HERE);
const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE); const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz);
const u32 type = _seg.type = prog.p_type; const u32 type = _seg.type = prog.p_type;
const u32 flag = _seg.flags = prog.p_flags; const u32 flag = _seg.flags = prog.p_flags;
_seg.filesz = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE); _seg.filesz = ::narrow<u32>(prog.p_filesz);
// Hash big-endian values // Hash big-endian values
sha1_update(&sha, reinterpret_cast<const uchar*>(&prog.p_type), sizeof(prog.p_type)); sha1_update(&sha, reinterpret_cast<const uchar*>(&prog.p_type), sizeof(prog.p_type));

View File

@ -409,7 +409,7 @@ void PPUTranslator::FlushRegisters()
Value* PPUTranslator::Solid(Value* value) Value* PPUTranslator::Solid(Value* value)
{ {
const u32 size = ::narrow<u32>(+value->getType()->getPrimitiveSizeInBits(), HERE); const u32 size = ::narrow<u32>(+value->getType()->getPrimitiveSizeInBits());
/* Workarounds (casting bool vectors directly may produce invalid code) */ /* Workarounds (casting bool vectors directly may produce invalid code) */
@ -586,7 +586,7 @@ llvm::Value* PPUTranslator::GetMemory(llvm::Value* addr, llvm::Type* type)
Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align) Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align)
{ {
const u32 size = ::narrow<u32>(+type->getPrimitiveSizeInBits(), HERE); const u32 size = ::narrow<u32>(+type->getPrimitiveSizeInBits());
if (is_be ^ m_is_be && size > 8) if (is_be ^ m_is_be && size > 8)
{ {
@ -603,7 +603,7 @@ Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align)
void PPUTranslator::WriteMemory(Value* addr, Value* value, bool is_be, u32 align) void PPUTranslator::WriteMemory(Value* addr, Value* value, bool is_be, u32 align)
{ {
const auto type = value->getType(); const auto type = value->getType();
const u32 size = ::narrow<u32>(+type->getPrimitiveSizeInBits(), HERE); const u32 size = ::narrow<u32>(+type->getPrimitiveSizeInBits());
if (is_be ^ m_is_be && size > 8) if (is_be ^ m_is_be && size > 8)
{ {

View File

@ -135,7 +135,7 @@ DECLARE(spu_runtime::tr_all) = []
*raw++ = 0x48; *raw++ = 0x48;
*raw++ = 0x8d; *raw++ = 0x8d;
*raw++ = 0x15; *raw++ = 0x15;
const s32 r32 = ::narrow<s32>(reinterpret_cast<u64>(g_dispatcher) - reinterpret_cast<u64>(raw) - 4, HERE); const s32 r32 = ::narrow<s32>(reinterpret_cast<u64>(g_dispatcher) - reinterpret_cast<u64>(raw) - 4);
std::memcpy(raw, &r32, 4); std::memcpy(raw, &r32, 4);
raw += 4; raw += 4;
@ -812,7 +812,7 @@ spu_function_t spu_runtime::rebuild_ubertrampoline(u32 id_inst)
if (w.rel32) if (w.rel32)
{ {
// Patch rel32 linking it to the current location if necessary // Patch rel32 linking it to the current location if necessary
const s32 r32 = ::narrow<s32>(raw - w.rel32, HERE); const s32 r32 = ::narrow<s32>(raw - w.rel32);
std::memcpy(w.rel32 - 4, &r32, 4); std::memcpy(w.rel32 - 4, &r32, 4);
} }

View File

@ -782,7 +782,7 @@ namespace
{ {
T min_index, max_index; T min_index, max_index;
u32 written; u32 written;
u32 remaining = ::size32(src, HERE); u32 remaining = ::size32(src);
if (s_use_sse4_1 && remaining >= 32) if (s_use_sse4_1 && remaining >= 32)
{ {
@ -956,7 +956,7 @@ namespace
T min_index = index_limit<T>(); T min_index = index_limit<T>();
T max_index = 0; T max_index = 0;
u32 written = 0; u32 written = 0;
u32 length = ::size32(src, HERE); u32 length = ::size32(src);
if (length >= 32 && !skip_restart) if (length >= 32 && !skip_restart)
{ {

View File

@ -701,7 +701,7 @@ namespace rsx
auto& verts_graph = compiled_resources.draw_commands.back().verts; auto& verts_graph = compiled_resources.draw_commands.back().verts;
const f32 x_stride = w * 1.f / m_datapoint_count; const f32 x_stride = w * 1.f / m_datapoint_count;
const u32 tail_index_offset = ::size32(m_datapoints, HERE) - m_datapoint_count; const u32 tail_index_offset = ::size32(m_datapoints) - m_datapoint_count;
for (u32 i = 0; i < m_datapoint_count; ++i) for (u32 i = 0; i < m_datapoint_count; ++i)
{ {

View File

@ -241,7 +241,7 @@ namespace rsx
} }
break; break;
default: default:
::narrow(tile->comp, "tile->comp" HERE); ::narrow(tile->comp);
} }
} }
@ -290,7 +290,7 @@ namespace rsx
} }
break; break;
default: default:
::narrow(tile->comp, "tile->comp" HERE); ::narrow(tile->comp);
} }
} }