Skip to content

Merge db98a70056ad8e84f90487ca3ea4205f2243dae2 into 5.5 #2958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/Index/IndexDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ bool IndexingContext::indexDeclContext(const DeclContext *DC) {
}

bool IndexingContext::indexTopLevelDecl(const Decl *D) {
if (D->getLocation().isInvalid())
if (!D || D->getLocation().isInvalid())
return true;

if (isa<ObjCMethodDecl>(D))
Expand Down
16 changes: 15 additions & 1 deletion lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3665,12 +3665,25 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
__FUNCTION__, arg, process->GetID());

EventSP event_sp;

// We need to ignore any packets that come in after we have
// have decided the process has exited. There are some
// situations, for instance when we try to interrupt a running
// process and the interrupt fails, where another packet might
// get delivered after we've decided to give up on the process.
// But once we've decided we are done with the process we will
// not be in a state to do anything useful with new packets.
// So it is safer to simply ignore any remaining packets by
// explicitly checking for eStateExited before reentering the
// fetch loop.

bool done = false;
while (!done) {
while (!done && process->GetPrivateState() != eStateExited) {
LLDB_LOGF(log,
"ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
") listener.WaitForEvent (NULL, event_sp)...",
__FUNCTION__, arg, process->GetID());

if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
const uint32_t event_type = event_sp->GetType();
if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
Expand Down Expand Up @@ -3769,6 +3782,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
} else {
process->SetExitStatus(-1, "lost connection");
}
done = true;
break;
}

Expand Down
69 changes: 68 additions & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1961,6 +1961,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(
const SourceLocationSpec &src_location_spec,
SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
const FileSpec &file_spec = src_location_spec.GetFileSpec();
const uint32_t line = src_location_spec.GetLine().getValueOr(0);
const bool check_inlines = src_location_spec.GetCheckInlines();
const uint32_t prev_size = sc_list.GetSize();
if (resolve_scope & eSymbolContextCompUnit) {
Expand All @@ -1973,7 +1975,72 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(
bool file_spec_matches_cu_file_spec = FileSpec::Match(
src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
SymbolContext sc(m_objfile_sp->GetModule());
sc.comp_unit = dc_cu;
uint32_t file_idx = UINT32_MAX;

// If we are looking for inline functions only and we don't find it
// in the support files, we are done.
if (check_inlines) {
file_idx =
sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true);
if (file_idx == UINT32_MAX)
continue;
}

if (line != 0) {
LineTable *line_table = sc.comp_unit->GetLineTable();

if (line_table != nullptr && line != 0) {
// We will have already looked up the file index if we are
// searching for inline entries.
if (!check_inlines)
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
1, file_spec, true);

if (file_idx != UINT32_MAX) {
uint32_t found_line;
uint16_t found_column;
uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex(
0, file_idx, src_location_spec, &sc.line_entry);
found_line = sc.line_entry.line;
found_column = sc.line_entry.column;

while (line_idx != UINT32_MAX) {
sc.function = nullptr;
sc.block = nullptr;
if (resolve_scope &
(eSymbolContextFunction | eSymbolContextBlock)) {
const lldb::addr_t file_vm_addr =
sc.line_entry.range.GetBaseAddress().GetFileAddress();
if (file_vm_addr != LLDB_INVALID_ADDRESS) {
ResolveFunctionAndBlock(
file_vm_addr, resolve_scope & eSymbolContextBlock, sc);
}
}

SourceLocationSpec found_location_spec(
file_spec, found_line, found_column,
/*check_inlines=*/false, /*exact=*/true);
sc_list.Append(sc);
line_idx = line_table->FindLineEntryIndexByFileIndex(
line_idx + 1, file_idx, found_location_spec,
&sc.line_entry);
}
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
// sites by file and line and if the file spec matches that of
// the compile unit
sc_list.Append(sc);
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
// sites by file and line and if the file spec matches that of
// the compile unit
sc_list.Append(sc);
}

if (!check_inlines)
break;
}
Expand Down
24 changes: 10 additions & 14 deletions lldb/source/Symbol/CompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,18 +254,6 @@ void CompileUnit::ResolveSymbolContext(
if (!file_spec_matches_cu_file_spec && !check_inlines)
return;

SymbolContext sc(GetModule());
sc.comp_unit = this;

if (line == 0) {
if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call sites by
// file and line and if the file spec matches that of the compile unit
sc_list.Append(sc);
}
return;
}

uint32_t file_idx =
GetSupportFiles().FindFileIndex(0, file_spec, true);
while (file_idx != UINT32_MAX) {
Expand All @@ -277,15 +265,23 @@ void CompileUnit::ResolveSymbolContext(
if (num_file_indexes == 0)
return;

LineTable *line_table = sc.comp_unit->GetLineTable();
SymbolContext sc(GetModule());
sc.comp_unit = this;

if (line_table == nullptr) {
if (line == 0) {
if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call sites by
// file and line and if the file spec matches that of the compile unit
sc_list.Append(sc);
}
return;
}

LineTable *line_table = sc.comp_unit->GetLineTable();

if (line_table == nullptr)
return;

uint32_t line_idx;
LineEntry line_entry;

Expand Down
36 changes: 27 additions & 9 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1810,19 +1810,30 @@ size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len,
if (!resolved_addr.IsValid())
resolved_addr = addr;

bool is_readonly = false;
// If we read from the file cache but can't get as many bytes as requested,
// we keep the result around in this buffer, in case this result is the
// best we can do.
std::unique_ptr<uint8_t[]> file_cache_read_buffer;
size_t file_cache_bytes_read = 0;

// Read from file cache if read-only section.
if (!force_live_memory && resolved_addr.IsSectionOffset()) {
SectionSP section_sp(resolved_addr.GetSection());
if (section_sp) {
auto permissions = Flags(section_sp->GetPermissions());
is_readonly = !permissions.Test(ePermissionsWritable) &&
permissions.Test(ePermissionsReadable);
}
if (is_readonly) {
bytes_read = ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
if (bytes_read > 0)
return bytes_read;
bool is_readonly = !permissions.Test(ePermissionsWritable) &&
permissions.Test(ePermissionsReadable);
if (is_readonly) {
file_cache_bytes_read =
ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
if (file_cache_bytes_read == dst_len)
return file_cache_bytes_read;
else if (file_cache_bytes_read > 0) {
file_cache_read_buffer =
std::make_unique<uint8_t[]>(file_cache_bytes_read);
std::memcpy(file_cache_read_buffer.get(), dst, file_cache_bytes_read);
}
}
}
}

Expand Down Expand Up @@ -1861,7 +1872,14 @@ size_t Target::ReadMemory(const Address &addr, void *dst, size_t dst_len,
}
}

if (!is_readonly && resolved_addr.IsSectionOffset()) {
if (file_cache_read_buffer && file_cache_bytes_read > 0) {
// Reading from the process failed. If we've previously succeeded in reading
// something from the file cache, then copy that over and return that.
std::memcpy(dst, file_cache_read_buffer.get(), file_cache_bytes_read);
return file_cache_bytes_read;
}

if (!file_cache_read_buffer && resolved_addr.IsSectionOffset()) {
// If we didn't already try and read from the object file cache, then try
// it after failing to read from the process.
return ReadMemoryFromFileCache(resolved_addr, dst, dst_len, error);
Expand Down
72 changes: 72 additions & 0 deletions lldb/test/API/functionalities/gdb_remote_client/TestHaltFails.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from __future__ import print_function
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from gdbclientutils import *


class TestHaltFails(GDBRemoteTestBase):

class MyResponder(MockGDBServerResponder):

def setBreakpoint(self, packet):
return "OK"

def interrupt(self):
# Simulate process waiting longer than the interrupt
# timeout to stop, then sending the reply.
time.sleep(14)
return "T02reason:signal"

def cont(self):
# No response, wait for the client to interrupt us.
return None

def wait_for_and_check_event(self, wait_time, value):
event = lldb.SBEvent()
got_event = self.dbg.GetListener().WaitForEvent(wait_time, event)
self.assertTrue(got_event, "Failed to get event after wait")
self.assertTrue(lldb.SBProcess.EventIsProcessEvent(event), "Event was not a process event")
event_type = lldb.SBProcess.GetStateFromEvent(event)
self.assertEqual(event_type, value)

def get_to_running(self):
self.server.responder = self.MyResponder()
self.target = self.createTarget("a.yaml")
process = self.connect(self.target)
self.dbg.SetAsync(True)

# There should be a stopped event, consume that:
self.wait_for_and_check_event(2, lldb.eStateStopped)
process.Continue()

# There should be a running event, consume that:
self.wait_for_and_check_event(2, lldb.eStateRunning)
return process

@skipIfReproducer # FIXME: Unexpected packet during (passive) replay
def test_destroy_while_running(self):
process = self.get_to_running()
process.Destroy()

# Again pretend that after failing to be interrupted, we delivered the stop
# and make sure we still exit properly.
self.wait_for_and_check_event(14, lldb.eStateExited)

@skipIfReproducer # FIXME: Unexpected packet during (passive) replay
def test_async_interrupt(self):
"""
Test that explicitly calling AsyncInterrupt, which then fails, leads
to an "eStateExited" state.
"""
process = self.get_to_running()
# Now do the interrupt:
process.SendAsyncInterrupt()

# That should have caused the Halt to time out and we should
# be in eStateExited:
self.wait_for_and_check_event(15, lldb.eStateExited)




Loading