Commit 9c5f1abc authored by jgruber's avatar jgruber Committed by Commit Bot

[builtins] Pad embedded builtins with int3

This fills the padding between builtins in the embedded blob with a
sequence of int3 instructions (ia32,x64).

Drive-by: Unify code zapping. We can add better support for other
architectures later.

Bug: v8:6666
Change-Id: Ibcb120ec18a8062d7527e0c6fe5ca86869c0dad8
Reviewed-on: https://chromium-review.googlesource.com/1167050
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54976}
parent e2fb86f8
......@@ -3915,7 +3915,7 @@ void MinorMarkCompactCollector::MakeIterable(
p->AddressToMarkbitIndex(free_start),
p->AddressToMarkbitIndex(free_end));
if (free_space_mode == ZAP_FREE_SPACE) {
memset(reinterpret_cast<void*>(free_start), 0xCC, size);
ZapCode(free_start, size);
}
p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size),
ClearRecordedSlots::kNo);
......@@ -3932,7 +3932,7 @@ void MinorMarkCompactCollector::MakeIterable(
p->AddressToMarkbitIndex(free_start),
p->AddressToMarkbitIndex(p->area_end()));
if (free_space_mode == ZAP_FREE_SPACE) {
memset(reinterpret_cast<void*>(free_start), 0xCC, size);
ZapCode(free_start, size);
}
p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size),
ClearRecordedSlots::kNo);
......
......@@ -279,7 +279,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
CHECK_GT(free_end, free_start);
size_t size = static_cast<size_t>(free_end - free_start);
if (free_space_mode == ZAP_FREE_SPACE) {
memset(reinterpret_cast<void*>(free_start), 0xCC, size);
ZapCode(free_start, size);
}
if (free_list_mode == REBUILD_FREE_LIST) {
freed_bytes = reinterpret_cast<PagedSpace*>(space)->Free(
......@@ -319,7 +319,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
CHECK_GT(p->area_end(), free_start);
size_t size = static_cast<size_t>(p->area_end() - free_start);
if (free_space_mode == ZAP_FREE_SPACE) {
memset(reinterpret_cast<void*>(free_start), 0xCC, size);
ZapCode(free_start, size);
}
if (free_list_mode == REBUILD_FREE_LIST) {
freed_bytes = reinterpret_cast<PagedSpace*>(space)->Free(
......
......@@ -330,9 +330,7 @@ Assembler::Assembler(const AssemblerOptions& options, void* buffer,
// caller in which case we can't be sure it's okay to overwrite
// existing code in it.
#ifdef DEBUG
if (own_buffer_) {
memset(buffer_, 0xCC, buffer_size_); // int3
}
if (own_buffer_) ZapCode(reinterpret_cast<Address>(buffer_), buffer_size_);
#endif
reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
......@@ -3194,7 +3192,7 @@ void Assembler::GrowBuffer() {
// Clear the buffer in debug mode. Use 'int3' instructions to make
// sure to get into problems if we ever run uninitialized code.
#ifdef DEBUG
memset(desc.buffer, 0xCC, desc.buffer_size);
ZapCode(reinterpret_cast<Address>(desc.buffer), desc.buffer_size);
#endif
// Copy the data.
......
......@@ -406,7 +406,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
metadata[i].instructions_length = length;
// Align the start of each instruction stream.
raw_data_size += RoundUp<kCodeAlignment>(length);
raw_data_size += PadAndAlign(length);
} else {
metadata[i].instructions_offset = raw_data_size;
}
......@@ -418,8 +418,12 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
"If in doubt, ask jgruber@");
const uint32_t blob_size = RawDataOffset() + raw_data_size;
uint8_t* blob = new uint8_t[blob_size];
std::memset(blob, 0, blob_size);
uint8_t* const blob = new uint8_t[blob_size];
uint8_t* const raw_data_start = blob + RawDataOffset();
// Initially zap the entire blob, effectively padding the alignment area
// between two builtins with int3's (on x64/ia32).
ZapCode(reinterpret_cast<Address>(blob), blob_size);
// Write the metadata tables.
DCHECK_EQ(MetadataSize(), sizeof(metadata[0]) * metadata.size());
......@@ -430,7 +434,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
if (!Builtins::IsIsolateIndependent(i)) continue;
Code* code = builtins->builtin(i);
uint32_t offset = metadata[i].instructions_offset;
uint8_t* dst = blob + RawDataOffset() + offset;
uint8_t* dst = raw_data_start + offset;
DCHECK_LE(RawDataOffset() + offset + code->raw_instruction_size(),
blob_size);
std::memcpy(dst, reinterpret_cast<uint8_t*>(code->raw_instruction_start()),
......
......@@ -96,7 +96,7 @@ class EmbeddedData final {
// Padded with kCodeAlignment.
uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
return RoundUp<kCodeAlignment>(InstructionSizeOfBuiltin(i));
return PadAndAlign(InstructionSizeOfBuiltin(i));
}
size_t CreateHash() const;
......@@ -130,7 +130,7 @@ class EmbeddedData final {
return sizeof(struct Metadata) * kTableSize;
}
static constexpr uint32_t RawDataOffset() {
return RoundUp<kCodeAlignment>(MetadataOffset() + MetadataSize());
return PadAndAlign(MetadataOffset() + MetadataSize());
}
private:
......@@ -141,6 +141,12 @@ class EmbeddedData final {
}
const uint8_t* RawData() const { return data_ + RawDataOffset(); }
static constexpr int PadAndAlign(int size) {
// Ensure we have at least one byte trailing the actual builtin
// instructions which we can later fill with int3.
return RoundUp<kCodeAlignment>(size + 1);
}
void PrintStatistics() const;
const uint8_t* data_;
......
......@@ -1716,6 +1716,15 @@ class ThreadedList final {
V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
Vector<const char> filter);
// Zap the specified area with a specific byte pattern. This currently defaults
// to int3 on x64 and ia32. On other architectures this will produce unspecified
// instruction sequences.
// TODO(jgruber): Better support for other architectures.
V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
static constexpr int kZapByte = 0xCC;
std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
}
} // namespace internal
} // namespace v8
......
......@@ -444,9 +444,7 @@ Assembler::Assembler(const AssemblerOptions& options, void* buffer,
// caller in which case we can't be sure it's okay to overwrite
// existing code in it.
#ifdef DEBUG
if (own_buffer_) {
memset(buffer_, 0xCC, buffer_size_); // int3
}
if (own_buffer_) ZapCode(reinterpret_cast<Address>(buffer_), buffer_size_);
#endif
ReserveCodeTargetSpace(100);
......@@ -630,7 +628,7 @@ void Assembler::GrowBuffer() {
// Clear the buffer in debug mode. Use 'int3' instructions to make
// sure to get into problems if we ever run uninitialized code.
#ifdef DEBUG
memset(desc.buffer, 0xCC, desc.buffer_size);
ZapCode(reinterpret_cast<Address>(desc.buffer), desc.buffer_size);
#endif
// Copy the data.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment