lttng.ust: Improve debug-info binary tracking
authorSimon Marchi <simon.marchi@polymtl.ca>
Tue, 28 Jun 2016 13:20:33 +0000 (09:20 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Sat, 9 Jul 2016 13:06:30 +0000 (09:06 -0400)
This patch improves the tracking of binary loading/unloading using the
LTTng statedump and dl events.

It changes the layout of the attributes in the state system to be this:

  Key                      Value
  /vpid                    -
  /vpid/<baddr>            <active>, 1 if active, null otherwise
  /vpid/<baddr>/build_id   <buildid>, e.g. "0123456789abcdef"
  /vpid/<baddr>/debug_link <debug_link>, e.g. "/usr/lib/libhello.so.debug"
  /vpid/<baddr>/memsz      <memsz>, e.g. 2127280
  /vpid/<baddr>/path       <path>, e.g. "/usr/lib/libhello.so"
  /vpid/<baddr>/is_pic     <is_pic>, 1 or 0

which is organized a bit more logically than the current approach.

Currently, the code expects the binaries to have a build id.  If this is
not the case for a particular binary, it will stay forever in the map of
pending binaries.  This patch checks the has_build_id to know whether or
not we should wait for such a corresponding build_id event.  While at
it, we do the same for debug link and propagate its value (although
nothing useful is done with it currently).

The "statedump start" event is now handled, which is required to
invalidate all the mappings for a certain vpid.

More tests are added, using the new synthetically generated traces from
CtfTestTrace.

Change-Id: I48c9de963129040dbd90ea492fe58eba441b28f3
Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca>
Signed-off-by: Alexandre Montplaisir <alexmonthy@efficios.com>
Reviewed-on: https://git.eclipse.org/r/73639
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
12 files changed:
lttng/org.eclipse.tracecompass.lttng2.ust.core.tests/src/org/eclipse/tracecompass/lttng2/ust/core/tests/analysis/debuginfo/UstDebugInfoAnalysisModuleTest.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/META-INF/MANIFEST.MF
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/FileOffsetMapper.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java [deleted file]
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java [deleted file]
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoStateProvider.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/trace/layout/LttngUst28EventLayout.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/BinaryCallsite.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoAnalysisModule.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryAspect.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java [new file with mode: 0644]

index 0c17a69ebda9e0df9c18f1c73e7d15d06c9ea87c..6d5c15027322b96127db705ca97f101b43a6ac8f 100644 (file)
@@ -21,9 +21,10 @@ import java.util.Comparator;
 import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryFile;
 import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoAnalysisModule;
 import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryAspect;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryFile;
+import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstEvent;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
@@ -52,7 +53,10 @@ import com.google.common.collect.Lists;
  */
 public class UstDebugInfoAnalysisModuleTest {
 
-    private static final @NonNull CtfTestTrace TEST_TRACE = CtfTestTrace.DEBUG_INFO3;
+    private static final @NonNull CtfTestTrace REAL_TEST_TRACE = CtfTestTrace.DEBUG_INFO4;
+    private static final @NonNull CtfTestTrace SYNTH_EXEC_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_EXEC;
+    private static final @NonNull CtfTestTrace SYNTH_TWO_PROCESSES_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_TWO_PROCESSES;
+    private static final @NonNull CtfTestTrace SYNTH_BUILDID_DEBUGLINK_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_BUILDID_DEBUGLINK;
     private static final @NonNull CtfTestTrace INVALID_TRACE = CtfTestTrace.CYG_PROFILE;
 
     private LttngUstTrace fTrace;
@@ -64,13 +68,6 @@ public class UstDebugInfoAnalysisModuleTest {
     @Before
     public void setup() {
         fModule = new UstDebugInfoAnalysisModule();
-        fTrace = new LttngUstTrace();
-        try {
-            fTrace.initTrace(null, CtfTmfTestTraceUtils.getTrace(TEST_TRACE).getPath(), CtfTmfEvent.class);
-        } catch (TmfTraceException e) {
-            /* Should not happen if tracesExist() passed */
-            throw new RuntimeException(e);
-        }
     }
 
     /**
@@ -78,12 +75,26 @@ public class UstDebugInfoAnalysisModuleTest {
      */
     @After
     public void tearDown() {
-        fTrace.dispose();
+        if (fTrace != null) {
+            fTrace.dispose();
+            fTrace = null;
+        }
+
         fModule.dispose();
-        fTrace = null;
         fModule = null;
     }
 
+    private @NonNull LttngUstTrace setupTrace(@NonNull CtfTestTrace testTrace) {
+        LttngUstTrace trace = new LttngUstTrace();
+        try {
+            trace.initTrace(null, CtfTmfTestTraceUtils.getTrace(testTrace).getPath(), CtfTmfEvent.class);
+        } catch (TmfTraceException e) {
+            fail(e.getMessage());
+        }
+        fTrace = trace;
+        return trace;
+    }
+
     /**
      * Test for {@link UstDebugInfoAnalysisModule#getAnalysisRequirements()}
      */
@@ -99,24 +110,18 @@ public class UstDebugInfoAnalysisModuleTest {
      */
     @Test
     public void testCanExecute() {
-        assertNotNull(fTrace);
-        assertTrue(fModule.canExecute(fTrace));
+        LttngUstTrace trace = setupTrace(REAL_TEST_TRACE);
+        assertTrue(fModule.canExecute(trace));
     }
 
     /**
      * Test that the analysis correctly refuses to execute on an invalid trace
      * (LTTng-UST < 2.8 in this case).
-     *
-     * @throws TmfTraceException
-     *             Should not happen
      */
     @Test
-    public void testCannotExcecute() throws TmfTraceException {
-        LttngUstTrace invalidTrace = new LttngUstTrace();
-        invalidTrace.initTrace(null, CtfTmfTestTraceUtils.getTrace(INVALID_TRACE).getPath(), CtfTmfEvent.class);
+    public void testCannotExcecute() {
+        LttngUstTrace invalidTrace = setupTrace(INVALID_TRACE);
         assertFalse(fModule.canExecute(invalidTrace));
-
-        invalidTrace.dispose();
     }
 
     private void executeModule() {
@@ -135,6 +140,7 @@ public class UstDebugInfoAnalysisModuleTest {
      */
     @Test
     public void testExecution() {
+        setupTrace(REAL_TEST_TRACE);
         executeModule();
         ITmfStateSystem ss = fModule.getStateSystem();
         assertNotNull(ss);
@@ -149,24 +155,25 @@ public class UstDebugInfoAnalysisModuleTest {
      */
     @Test
     public void testBinaryCallsites() {
-        assertNotNull(fTrace);
+        LttngUstTrace trace = setupTrace(REAL_TEST_TRACE);
+
         /*
          * Fake a "trace opened" signal, so that the relevant analyses are
          * started.
          */
-        TmfTraceOpenedSignal signal = new TmfTraceOpenedSignal(this, fTrace, null);
+        TmfTraceOpenedSignal signal = new TmfTraceOpenedSignal(this, trace, null);
         TmfSignalManager.dispatchSignal(signal);
 
         /* Send a request to get the 3 events we are interested in */
         List<@NonNull LttngUstEvent> events = new ArrayList<>();
-        TmfEventRequest request = new TmfEventRequest(LttngUstEvent.class, 287, 3, ExecutionType.FOREGROUND) {
+        TmfEventRequest request = new TmfEventRequest(LttngUstEvent.class, 31, 1, ExecutionType.FOREGROUND) {
             @Override
             public void handleData(ITmfEvent event) {
                 super.handleData(event);
                 events.add((LttngUstEvent) event);
             }
         };
-        fTrace.sendRequest(request);
+        trace.sendRequest(request);
         try {
             request.waitForCompletion();
         } catch (InterruptedException e) {
@@ -177,16 +184,83 @@ public class UstDebugInfoAnalysisModuleTest {
         final UstDebugInfoBinaryAspect aspect = UstDebugInfoBinaryAspect.INSTANCE;
 
         String actual = checkNotNull(aspect.resolve(events.get(0))).toString();
-        String expected = "/home/alexandre/src/lttng-project/lttng/trace-utils/dynamicLinking/libhello.so+0x15ae";
+        String expected = "/home/simark/src/babeltrace/tests/debug-info-data/libhello_so+0x14d4";
         assertEquals(expected, actual);
+    }
 
-        actual = checkNotNull(aspect.resolve(events.get(1))).toString();
-        expected = "/home/alexandre/src/lttng-project/lttng/trace-utils/dynamicLinking/libhello.so+0x1680";
-        assertEquals(expected, actual);
+    /**
+     * Test the analysis with a test trace doing an "exec" system call.
+     */
+    @Test
+    public void testExec() {
+        UstDebugInfoLoadedBinaryFile matchingFile, expected;
 
-        actual = checkNotNull(aspect.resolve(events.get(2))).toString();
-        expected = "/home/alexandre/src/lttng-project/lttng/trace-utils/dynamicLinking/libhello.so+0x1745";
-        assertEquals(expected, actual);
+        int vpid = 1337;
+
+        setupTrace(SYNTH_EXEC_TRACE);
+        executeModule();
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo", null, null, false);
+        matchingFile = fModule.getMatchingFile(4000000, vpid, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = null;
+        matchingFile = fModule.getMatchingFile(8000000, vpid, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x500000, "/tmp/bar", null, null, false);
+        matchingFile = fModule.getMatchingFile(9000000, vpid, 0x500100);
+        assertEquals(expected, matchingFile);
+    }
+
+    /**
+     * Test the analysis with a test trace with two processes doing a statedump
+     * simultaneously.
+     */
+    @Test
+    public void testTwoProcesses() {
+        UstDebugInfoLoadedBinaryFile matchingFile, expected;
+        int vpid1 = 1337;
+        int vpid2 = 2001;
+
+        setupTrace(SYNTH_TWO_PROCESSES_TRACE);
+        executeModule();
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "/tmp/debuglink1", false);
+        matchingFile = fModule.getMatchingFile(11000000, vpid1, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/bar", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "/tmp/debuglink2", false);
+        matchingFile = fModule.getMatchingFile(12000000, vpid2, 0x400100);
+        assertEquals(expected, matchingFile);
+    }
+
+
+    /**
+     * Test the analysis with a trace with debug_link information.
+     */
+    @Test
+    public void testBuildIDDebugLink() {
+        UstDebugInfoLoadedBinaryFile matchingFile, expected;
+
+        setupTrace(SYNTH_BUILDID_DEBUGLINK_TRACE);
+        executeModule();
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_nn", null, null, false);
+        matchingFile = fModule.getMatchingFile(17000000, 1337, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_yn", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", null, false);
+        matchingFile = fModule.getMatchingFile(18000000, 1338, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_ny", null, "/tmp/debug_link1", false);
+        matchingFile = fModule.getMatchingFile(19000000, 1339, 0x400100);
+        assertEquals(expected, matchingFile);
+
+        expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_yy", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "/tmp/debug_link2", false);
+        matchingFile = fModule.getMatchingFile(20000000, 1340, 0x400100);
+        assertEquals(expected, matchingFile);
     }
 
     /**
@@ -194,62 +268,38 @@ public class UstDebugInfoAnalysisModuleTest {
      */
     @Test
     public void testGetAllBinaries() {
+        setupTrace(REAL_TEST_TRACE);
         executeModule();
+
         List<UstDebugInfoBinaryFile> actualBinaries = Lists.newArrayList(fModule.getAllBinaries());
         List<UstDebugInfoBinaryFile> expectedBinaries = Lists.newArrayList(
-                new UstDebugInfoBinaryFile("/home/alexandre/src/lttng-project/lttng/trace-utils/dynamicLinking/libhello.so", "c9ac43c6b4251b0789ada66931e33487d65f64a6", true),
-                new UstDebugInfoBinaryFile("/home/alexandre/src/lttng-project/lttng/trace-utils/dynamicLinking/main.out", "0ec3294d0cacff93ec30b7161ff21efcd4cdd327", false),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/ld-2.23.so", "edfa6d46e00ca97f349fdd3333d88493d442932c", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libc-2.23.so", "369de0e1d833caa693af17f17c83ba937f0a4dad", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libdl-2.23.so", "a2adf3615338d49c702c41eb83a99ab743d2b574", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libgcc_s.so.1", "68220ae2c65d65c1b6aaa12fa6765a6ec2f5f434", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libglib-2.0.so.0.4800.0", "8b553ecf9133c50f36a7345a4924c5b97e9daa11", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/liblzma.so.5.0.0", "15aed4855920e5a0fb8791b683eb88c7e1199260", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libm-2.23.so", "5c4078c04888a418f3db0868702ecfdb35b3ad8b", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libpcre.so.3.13.2", "390b2228e9a1071bb0be285d77b6669cb37ce628", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libpthread-2.23.so", "b77847cc9cacbca3b5753d0d25a32e5795afe75b", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libresolv-2.23.so", "81ef82040e9877e63adca93b365f52a4bb831ee1", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/librt-2.23.so", "a779dbcb3a477dc0c8d09b60fac7335d396c19df", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libselinux.so.1", "62a57085aa17036efdcecf6655d9e7be566f6948", true),
-                new UstDebugInfoBinaryFile("/lib/x86_64-linux-gnu/libz.so.1.2.8", "340b7b463f981b8a0fb3451751f881df1b0c2f74", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/indicator-transfer/indicator-transfer-service", "01c605bcf38d068d77a6e0a02cede6a50c5750b5", false),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/indicator-transfer/libbuteo-transfers.so", "a3a54ba90d7b7b67e0be9baaae3b91675b630a09", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/indicator-transfer/libdmtransfers.so", "ad8ebd563d733818f9f4a399b8d34c1b7e846f3d", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libQt5Core.so.5.5.1", "478d22fbdf6a3e0ec3b499bd2bb8e97dbed84fb6", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libQt5Xml.so.5.5.1", "3a16f2feccfdbca6a40d9bd43ae5a966bca065c7", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libaccounts-glib.so.0.1.3", "3aaeb6f74d07bd2331fa1664a90b11ca5cc1b71e", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libaccounts-qt5.so.1.2.0", "c4c36b5efb4dd5f92a53ed0a2844239f564328d7", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.58.0", "8cebf2501fd917f393ef1390777415fca9289878", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0", "bb484981ddf4152bb6f02ad3a700ec21ca3805e2", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libclick-0.4.so.0.4.0", "79609d999eab77f934f6d7d296074ea54f1410e8", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libffi.so.6.0.4", "9d9c958f1f4894afef6aecd90d1c430ea29ac34f", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libgee-0.8.so.2.5.1", "96aff01de4c5e4817d483de7278c8cc9c6d02001", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.4800.0", "01d955da82f10209b515f362b2352d5a0d0b5330", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0.4800.0", "a9190276f6246d3a44ba820510ef7d469ea556b1", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4800.0", "bce3f25958a5b88c9493990daf0c90a787444c28", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libicudata.so.55.1", "233845f0cd27642c4b2cc43979c8801b52bc00a9", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libicui18n.so.55.1", "7bf3774116dbb992ffcc2156b6f5c44f0a328f00", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libicuuc.so.55.1", "323e4878073bb4e0d7b174ae24e383ec5e05d68a", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libindicator-transfer.so.0.0.2", "4e472120f2a19343e1ff5928459edcb4a6c0b1e2", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libjson-glib-1.0.so.0.102.0", "55c87753a67b0c24922bd091f042b9d8bd4995dc", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liblttng-ust-dl.so.0.0.0", "450c14d5a7a72780b2d88a3cf73d2e12c2774676", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liblttng-ust-tracepoint.so.0.0.0", "e70e1748e137bb59b542e15e0722455b998355fc", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liblttng-ust.so.0.0.0", "101115876419ead3a8bd9a9a08a6d92984015b99", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libmirclient.so.9", "b4c1509382d3ef5f7458db59710b4d30dad86b5d", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libmircommon.so.5", "25b5830854701533323f15195ae9e501ad7f772b", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libmirprotobuf.so.3", "2f6b1a56f1ac43ae001dffde4dc1a24bfee04dec", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libpcre16.so.3.13.2", "2cc13260733c5b35f311725fca88219b338d5390", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libprotobuf-lite.so.9.0.1", "625eb54ba7ccc3af18d3193e22cbe9f23dfb88e5", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6", "d9782ba023caec26b15d8676e3a5d07b55e121ef", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21", "662f4598d7854c6731f13802486e477a7bdb09c7", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libubuntu-app-launch.so.2.0.0", "1e5753f4feda98548bd230eb07b81e330f419463", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liburcu-bp.so.4.0.0", "d208fcd0e6e6968b8110d9c487f63ae1a400e7c2", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liburcu-cds.so.4.0.0", "177fbd0a1b21145ad2f29bf41ba9f45e43b1ae4a", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/liburl-dispatcher.so.1.0.0", "58e7febb6e33418eee311c0bad19aace5cba0fd1", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libxkbcommon.so.0.0.0", "29ebf0cc0837b321e6a751b9b7d43ae9f8f3f0c0", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libxml2.so.2.9.3", "a155c7bc345d0e0b711be09120204bd88f475f9e", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/libzeitgeist-2.0.so.0.0.0", "211049ef6c5ed6e7bbcdc75c0a25d1f11755151d", true),
-                new UstDebugInfoBinaryFile("/usr/lib/x86_64-linux-gnu/url-dispatcher/url-dispatcher", "694fcf16ee9241e66a33de671d10f854312e0c87", false));
+                new UstDebugInfoBinaryFile("/home/simark/src/babeltrace/tests/debug-info-data/libhello_so",
+                                           "cdd98cdd87f7fe64c13b6daad553987eafd40cbb", null, true),
+                new UstDebugInfoBinaryFile("/home/simark/src/babeltrace/tests/debug-info-data/test",
+                                           "0683255d2cf219c33cc0efd6039db09ccc4416d7", null, false),
+                new UstDebugInfoBinaryFile("[linux-vdso.so.1]", null, null, false),
+                new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust-dl.so.0.0.0",
+                                           "39c035014cc02008d6884fcb1be4e020cc820366", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/libdl-2.23.so",
+                                           "db3f9be9f4ebe9e2a21e4ae0b4ef7165d40fdfef", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/libc-2.23.so",
+                                           "946025a5cad7b5f2dfbaebc6ebd1fcc004349b48", null, true),
+                new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust.so.0.0.0",
+                                           "405b0b15daa73eccb88076247ba30356c00d3b92", null, true),
+                new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust-tracepoint.so.0.0.0",
+                                           "62c028aad38adb5e0910c527d522e8c86a0a3344", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/librt-2.23.so",
+                                           "aba676bda7fb6adb71e100159915504e1a0c17e6", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/liburcu-bp.so.4.0.0",
+                                           "b9dfadea234107f8453bc636fc160047e0c01b7a", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/liburcu-cds.so.4.0.0",
+                                           "420527f6dacc762378d9fa7def54d91c80a6c87e", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/libpthread-2.23.so",
+                                           "d91ed99c8425b7ce5da5bb750662a91038e02a78", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/ld-2.23.so",
+                                           "524eff0527e923e4adc4be9db1ef7475607b92e8", null, true),
+                new UstDebugInfoBinaryFile("/usr/lib/liburcu-common.so.4.0.0",
+                                           "f279a6d46a2b846e15e7abd99cfe9fbe8d7f8295", null, true));
 
         Comparator<UstDebugInfoBinaryFile> comparator = Comparator.comparing(UstDebugInfoBinaryFile::getFilePath);
         actualBinaries.sort(comparator);
index 478f3a0bff4b4f09707a317ee68aeeb1679501c8..668093b6486ec8ad1929f4b9e4b82a2cb184b3da 100644 (file)
@@ -24,7 +24,8 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.tracecompass.tmf.ctf.core,
  org.eclipse.tracecompass.lttng2.control.core,
  org.eclipse.tracecompass.ctf.core
-Import-Package: com.google.common.base,
+Import-Package: com.google.common.annotations;version="15.0.0",
+ com.google.common.base,
  com.google.common.cache,
  com.google.common.collect,
  com.google.common.io
index c2fe8d4e1107a0dbda560881c8290d2503b93bbe..69c7b1f6661ddd5382bbeab5a5945c3bdfdfe783 100644 (file)
@@ -51,10 +51,10 @@ public final class FileOffsetMapper {
     private static class FileOffset {
 
         private final String fFilePath;
-        private final String fBuildId;
+        private final @Nullable String fBuildId;
         private final long fOffset;
 
-        public FileOffset(String filePath, String buildId, long offset) {
+        public FileOffset(String filePath, @Nullable String buildId, long offset) {
             fFilePath = filePath;
             fBuildId = buildId;
             fOffset = offset;
@@ -119,7 +119,7 @@ public final class FileOffsetMapper {
      * @return The list of callsites corresponding to the offset, reported from
      *         the "highest" inlining location, down to the initial definition.
      */
-    public static @Nullable Iterable<SourceCallsite> getCallsiteFromOffset(File file, String buildId, long offset) {
+    public static @Nullable Iterable<SourceCallsite> getCallsiteFromOffset(File file, @Nullable String buildId, long offset) {
         if (!Files.exists((file.toPath()))) {
             return null;
         }
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java b/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java
deleted file mode 100644 (file)
index b467720..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo;
-
-import java.util.Objects;
-
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * Wrapper class to reference to a particular binary, which can be an
- * executable or library. It contains both the complete file path (at the
- * time the trace was taken) and the build ID of the binary.
- */
-public class UstDebugInfoBinaryFile implements Comparable<UstDebugInfoBinaryFile> {
-
-    private final String fFilePath;
-    private final String fBuildId;
-    private final boolean fIsPic;
-    private final String fToString;
-
-    /**
-     * Constructor
-     *
-     * @param filePath
-     *            The binary's path on the filesystem
-     * @param buildId
-     *            The binary's unique buildID (in base16 form).
-     * @param isPic
-     *            If the binary is position-independent or not
-     */
-    public UstDebugInfoBinaryFile(String filePath, String buildId, boolean isPic) {
-        fFilePath = filePath;
-        fBuildId = buildId;
-        fIsPic = isPic;
-
-        fToString = filePath + " (" + //$NON-NLS-1$
-                (fIsPic ? "PIC" : "non-PIC") + //$NON-NLS-1$ //$NON-NLS-2$
-                ", " + buildId + ')'; //$NON-NLS-1$
-    }
-
-    /**
-     * Get the file's path, as was referenced to in the trace.
-     *
-     * @return The file path
-     */
-    public String getFilePath() {
-        return fFilePath;
-    }
-
-    /**
-     * Get the build ID of the binary. It should be a unique identifier.
-     *
-     * On Unix systems, you can use <pre>eu-readelf -n [binary]</pre> to get
-     * this ID.
-     *
-     * @return The file's build ID.
-     */
-    public String getBuildId() {
-        return fBuildId;
-    }
-
-    /**
-     * Return whether the given file (binary or library) is Position-Independent
-     * Code or not.
-     *
-     * This indicates whether the symbols in the ELF are absolute or relative to
-     * the runtime base address, and determines which address we need to pass to
-     * 'addr2line'.
-     *
-     * @return Whether this file is position-independent or not
-     */
-    public boolean isPic() {
-        return fIsPic;
-    }
-
-    @Override
-    public String toString() {
-        return fToString;
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (!(obj instanceof UstDebugInfoBinaryFile)) {
-            return false;
-        }
-        UstDebugInfoBinaryFile other = (UstDebugInfoBinaryFile) obj;
-        return (fFilePath.equals(other.fFilePath) &&
-                fBuildId.equals(other.fBuildId) &&
-                fIsPic == other.fIsPic);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(fBuildId, fFilePath, fIsPic);
-    }
-
-    /**
-     * Used for sorting. Sorts by using alphabetical order of the file
-     * paths.
-     */
-    @Override
-    public int compareTo(@Nullable UstDebugInfoBinaryFile o) {
-        if (o == null) {
-            return 1;
-        }
-        return fFilePath.compareTo(o.fFilePath);
-    }
-}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java b/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java
deleted file mode 100644 (file)
index 993af78..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo;
-
-/**
- * Simple extension to {@link UstDebugInfoBinaryFile} that adds the base address at
- * which the given binary or library is loaded.
- *
- * @author Alexandre Montplaisir
- */
-public class UstDebugInfoLoadedBinaryFile extends UstDebugInfoBinaryFile {
-
-    private final long baseAddress;
-
-    /**
-     * Constructor
-     *
-     * @param baseAddress
-     *            The base address at which the binary or library is loaded
-     * @param filePath
-     *            The file path of the loaded binary/library
-     * @param buildId
-     *            The build ID of the binary object
-     * @param isPic
-     *            If the binary is position-independent or not
-     */
-    public UstDebugInfoLoadedBinaryFile(long baseAddress, String filePath, String buildId, boolean isPic) {
-        super(filePath, buildId, isPic);
-        this.baseAddress = baseAddress;
-    }
-
-    /**
-     * Return the base address at which the object is loaded.
-     *
-     * @return The base address
-     */
-    public long getBaseAddress() {
-        return baseAddress;
-    }
-}
index 565716b9645adde21264abba84814d7ab2b8c6db..de04196fd974dc9a5ed1150fb2ef7fb60c4260d8 100644 (file)
@@ -13,19 +13,22 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.logging.Logger;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.Activator;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.log.TraceCompassLog;
 import org.eclipse.tracecompass.internal.lttng2.ust.core.trace.layout.LttngUst28EventLayout;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
 import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
-import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
 import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.util.Pair;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.io.BaseEncoding;
@@ -37,51 +40,49 @@ import com.google.common.io.BaseEncoding;
  * The layout of the generated attribute tree will look like this:
  *
  * <pre>
- *  * [root]
- *   +-- 1000
- *   +-- 2000
- *  ...
- *   +-- 3000 (VPIDs)
- *        +-- baddr (value = addr range end, long)
- *        |     +-- buildId (value = /path/to/library (sopath), string)
- *        |           +- is_pic (value = 0 or 1 (int))
- *        +-- baddr
- *        |     +-- buildId1
- *        |           +- is_pic
- *        |     +-- buildId2 (if the same address is re-used later)
- *        |           +- is_pic
- *       ...
+ * Key                       Value
+ * /vpid                     null
+ * /vpid/<baddr>             Integer 1 if the memory mapping active at this
+ *                           point in time, null otherwise.
+ * /vpid/<baddr>/build_id    Build ID of the binary as an hex string, e.g.
+ *                           "0123456789abcdef", or null if it doesn't have a
+ *                           build id.
+ * /vpid/<baddr>/debug_link  Path to the separate debug info of the binary, e.g.
+ *                           "/usr/lib/libhello.so.debug", or null if it doesn't
+ *                           have separate debug info.
+ * /vpid/<baddr>/memsz       Size of the memory mapping in bytes.
+ * /vpid/<baddr>/path        Path to the binary, e.g. "/usr/lib/libhello.so".
+ * /vpid/<baddr>/is_pic      Integer 1 if the binary contains position
+ *                           independent code, 0 otherwise.
  * </pre>
  *
- * The "baddr" attribute name will represent the range start as a string, and
- * its value will be range end. If null, it means this particular library is not
- * loaded at this location at the moment.
- *
- * This sits under the mtime (modification time of the file) attribute. This is
- * to handle cases like multiple concurrent dlopen's of the same library, or the
- * very mind-blowing edge case of a file being modified and being reloaded later
- * on, possibly side-by-side with its previous version.
- *
- * Since the state system is not a spatial database, it's not really worth
- * indexing by memory ranges, and since the amount of loaded libraries is
- * usually small, we should afford to iterate through all mappings to find each
- * match.
- *
- * Still, for better scalability (and for science), it could be interesting to
- * look into storing the memory-model-over-time in something like an R-Tree.
+ * The "baddr" attribute name represents the memory mapping base address a
+ * string (in decimal).
  *
  * @author Alexandre Montplaisir
+ * @author Simon Marchi
  */
 public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
 
-    /**
-     * Sub-attribute indicating if a given binary is PIC (position-independent
-     * code) or not. This information is present directly in the trace.
-     */
-    public static final String IS_PIC_ATTRIB  = "is_pic"; //$NON-NLS-1$
+    /** State system attribute name for the in-memory binary size */
+    public static final String MEMSZ_ATTRIB = "memsz"; //$NON-NLS-1$
+
+    /** State system attribute name for the binary path */
+    public static final String PATH_ATTRIB = "path"; //$NON-NLS-1$
+
+    /** State system attribute name for the PICness of the binary */
+    public static final String IS_PIC_ATTRIB = "is_pic"; //$NON-NLS-1$
 
-    /* Version of this state provider */
-    private static final int VERSION = 2;
+    /** State system attribute name for the build ID of the binary */
+    public static final String BUILD_ID_ATTRIB = "build_id"; //$NON-NLS-1$
+
+    /** State system attribute name for the debug link of the binary */
+    public static final String DEBUG_LINK_ATTRIB = "debug_link"; //$NON-NLS-1$
+
+    /** Version of this state provider */
+    private static final int VERSION = 3;
+
+    private static final Logger LOGGER = TraceCompassLog.getLogger(UstDebugInfoStateProvider.class);
 
     private static final int DL_DLOPEN_INDEX = 1;
     private static final int DL_BUILD_ID_INDEX = 2;
@@ -90,31 +91,66 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
     private static final int STATEDUMP_BIN_INFO_INDEX = 5;
     private static final int STATEDUMP_BUILD_ID_INDEX = 6;
     private static final int STATEDUMP_DEBUG_LINK_INDEX = 7;
+    private static final int STATEDUMP_START_INDEX = 8;
 
     private final LttngUst28EventLayout fLayout;
     private final Map<String, Integer> fEventNames;
 
-    /**
-     * We need both the soinfo/dlopen event AND the matching build_id/debug_link
-     * event to get all the information about a particular binary.
-     *
-     * Between these two events, we will store the <baddr, BinInfo> in here.
+    /*
+     * Store for data that is incomplete, for which we are waiting for some
+     * upcoming events (build_id or debug_link). Maps <vpid, baddr> to
+     * PendingBinInfo object.
      */
-    private final Map<Long, BinInfo> fPendingEntries = new HashMap<>();
+    private final Map<Pair<Long, Long>, PendingBinInfo> fPendingBinInfos = new HashMap<>();
 
-    /**
-     * Information contained in a "bin_info" event, which means a binary's path,
-     * base address, and if it is a PIC or not.
-     */
-    private static class BinInfo {
-        public final long fBaddr;
-        public final String fPath;
-        public final int fIsPic;
+    private class PendingBinInfo {
+
+        /* The event data, saved here until we put everything in the state system. */
+        private final long fVpid;
+        private final long fBaddr;
+        private final long fMemsz;
+        private final String fPath;
+        private final boolean fIsPIC;
+
+        private @Nullable String fBuildId = null;
+        private @Nullable String fDebugLink = null;
 
-        public BinInfo(long baddr, String path, int isPic) {
+        /* Which info are we waiting for? */
+        private boolean fBuildIdPending;
+        private boolean fDebugLinkPending;
+
+        public PendingBinInfo(boolean hasBuildId, boolean hasDebugLink,
+                long vpid, long baddr, long memsz, String path, boolean isPIC) {
+            fVpid = vpid;
             fBaddr = baddr;
+            fMemsz = memsz;
             fPath = path;
-            fIsPic = isPic;
+            fIsPIC = isPIC;
+
+            fBuildIdPending = hasBuildId;
+            fDebugLinkPending = hasDebugLink;
+        }
+
+        boolean done() {
+            return !(fBuildIdPending || fDebugLinkPending);
+        }
+
+        public void setBuildId(String buildId) {
+            fBuildIdPending = false;
+            fBuildId = buildId;
+        }
+
+        public @Nullable String getBuildId() {
+            return fBuildId;
+        }
+
+        public void setDebugLink(String debugLink) {
+            fDebugLinkPending = false;
+            fDebugLink = debugLink;
+        }
+
+        public @Nullable String getDebugLink() {
+            return fDebugLink;
         }
     }
 
@@ -144,6 +180,7 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
         builder.put(layout.eventStatedumpBinInfo(), STATEDUMP_BIN_INFO_INDEX);
         builder.put(layout.eventStateDumpBuildId(), STATEDUMP_BUILD_ID_INDEX);
         builder.put(layout.eventStateDumpDebugLink(), STATEDUMP_DEBUG_LINK_INDEX);
+        builder.put(layout.eventStatedumpStart(), STATEDUMP_START_INDEX);
         return builder.build();
     }
 
@@ -169,71 +206,178 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
         }
         int intIndex = index.intValue();
 
+        switch (intIndex) {
+        case STATEDUMP_START_INDEX: {
+            handleStatedumpStart(event, vpid, ss);
+            break;
+        }
+
+        case DL_DLOPEN_INDEX:
+        case STATEDUMP_BIN_INFO_INDEX: {
+            handleOpen(event, vpid, ss);
+            break;
+        }
+
+        case DL_BUILD_ID_INDEX:
+        case STATEDUMP_BUILD_ID_INDEX: {
+            handleBuildId(event, vpid, ss);
+            break;
+        }
+
+        case DL_DEBUG_LINK_INDEX:
+        case STATEDUMP_DEBUG_LINK_INDEX: {
+            handleDebugLink(event, vpid, ss);
+            break;
+        }
+
+        case DL_DLCLOSE_INDEX: {
+            handleClose(event, vpid, ss);
+            break;
+        }
+
+        default:
+            /* Ignore other events */
+            break;
+        }
+    }
+
+    /**
+     * Commit the binary information contained in pending to the state system.
+     *
+     * This method should only be called when there is no more pending
+     * information for that binary.
+     */
+    private static void commitPendingToStateSystem(PendingBinInfo pending,
+            long ts, ITmfStateSystemBuilder ss) {
+        if (!pending.done()) {
+            throw new IllegalStateException();
+        }
+
+        long vpid = pending.fVpid;
+        long baddr = pending.fBaddr;
+        long memsz = pending.fMemsz;
+        String path = pending.fPath;
+        String buildId = pending.getBuildId();
+        String debugLink = pending.getDebugLink();
+        boolean isPIC = pending.fIsPIC;
+
+        /* Create the "top-level" attribute for this object. */
+        int baddrQuark = ss.getQuarkAbsoluteAndAdd(Long.toString(vpid), Long.toString(baddr));
+
+        /* Create the attributes that contain actual data. */
+        int memszQuark = ss.getQuarkRelativeAndAdd(baddrQuark, MEMSZ_ATTRIB);
+        int pathQuark = ss.getQuarkRelativeAndAdd(baddrQuark, PATH_ATTRIB);
+        int isPICQuark = ss.getQuarkRelativeAndAdd(baddrQuark, IS_PIC_ATTRIB);
+        int buildIdQuark = ss.getQuarkRelativeAndAdd(baddrQuark, BUILD_ID_ATTRIB);
+        int debugLinkQuark = ss.getQuarkRelativeAndAdd(baddrQuark, DEBUG_LINK_ATTRIB);
         try {
-            switch (intIndex) {
-            case DL_DLOPEN_INDEX:
-            case STATEDUMP_BIN_INFO_INDEX:
-            {
-                handleOpen(event, vpid, ss);
-                break;
+            ss.modifyAttribute(ts, TmfStateValue.newValueInt(1), baddrQuark);
+            ss.modifyAttribute(ts, TmfStateValue.newValueLong(memsz), memszQuark);
+            ss.modifyAttribute(ts, TmfStateValue.newValueString(path), pathQuark);
+            ss.modifyAttribute(ts, TmfStateValue.newValueInt(isPIC ? 1 : 0), isPICQuark);
+            if (buildId != null) {
+                ss.modifyAttribute(ts, TmfStateValue.newValueString(buildId), buildIdQuark);
+            } else {
+                ss.modifyAttribute(ts, TmfStateValue.nullValue(), buildIdQuark);
             }
 
-            case DL_BUILD_ID_INDEX:
-            case STATEDUMP_BUILD_ID_INDEX:
-            {
-                handleBuildId(event, vpid, ss);
-                break;
+            if (debugLink != null) {
+                ss.modifyAttribute(ts,  TmfStateValue.newValueString(debugLink), debugLinkQuark);
+            } else {
+                ss.modifyAttribute(ts, TmfStateValue.nullValue(), debugLinkQuark);
             }
+        } catch (StateValueTypeException e) {
+            /* Something went very wrong. */
+            throw new IllegalStateException(e);
+        }
+    }
 
-            case DL_DEBUG_LINK_INDEX:
-            case STATEDUMP_DEBUG_LINK_INDEX:
-            /* Fields: Long baddr, Long crc, String filename */
-            {
-                // TODO NYI
-                break;
-            }
+    /**
+     * Locate a PendingBinInfo object in the map of pending binary informations
+     * with the key <vpid, baddr>. Remove it from the map and return it if it is
+     * found, return null otherwise.
+     */
+    private @Nullable PendingBinInfo retrievePendingBinInfo(long vpid, long baddr) {
+        Pair<Long, Long> key = new Pair<>(vpid, baddr);
 
-            case DL_DLCLOSE_INDEX:
-            {
-                handleClose(event, vpid, ss);
-                break;
-            }
+        return fPendingBinInfos.remove(key);
+    }
 
-            default:
-                /* Ignore other events */
-                break;
-            }
+    /**
+     * Check whether we know everything there is to know about the binary
+     * described by pending, and if so, commit it to the state system.
+     * Otherwise, put it in the map of pending binary informations.
+     */
+    private void processPendingBinInfo(PendingBinInfo pending, long ts,
+            ITmfStateSystemBuilder ss) {
+        if (pending.done()) {
+            commitPendingToStateSystem(pending, ts, ss);
+        } else {
+            /* We are expecting more data for this binary, put in the pending map. */
+            Pair<Long, Long> key = new Pair<>(pending.fVpid, pending.fBaddr);
+
+            fPendingBinInfos.put(key, pending);
+        }
+    }
+
+    /**
+     * Handle the start of a statedump.
+     *
+     * When a process does an exec, a new statedump is done and all previous
+     * mappings are now invalid.
+     */
+    private static void handleStatedumpStart(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) {
+        try {
+            long ts = event.getTimestamp().getValue();
+            int vpidQuark = ss.getQuarkAbsolute(vpid.toString());
+
+            ss.removeAttribute(ts, vpidQuark);
         } catch (AttributeNotFoundException e) {
-            Activator.getDefault().logError("Unexpected exception in UstDebugInfoStateProvider", e); //$NON-NLS-1$
+            /* We didn't know anything about this vpid yet, so there is nothing to remove. */
         }
     }
 
     /**
      * Handle opening a shared library.
      *
-     * Uses fields: Long baddr, Long memsz, String sopath
+     * Uses fields: Long baddr, Long memsz, String path, Long is_pic
      */
     private void handleOpen(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) {
-        Long baddr = (Long) event.getContent().getField(fLayout.fieldBaddr()).getValue();
-        Long memsz = (Long) event.getContent().getField(fLayout.fieldMemsz()).getValue();
-        String sopath = (String) event.getContent().getField(fLayout.fieldPath()).getValue();
+        Long baddr = event.getContent().getFieldValue(Long.class, fLayout.fieldBaddr());
+        Long memsz = event.getContent().getFieldValue(Long.class, fLayout.fieldMemsz());
+        String path = event.getContent().getFieldValue(String.class, fLayout.fieldPath());
+        Long hasBuildIdValue = event.getContent().getFieldValue(Long.class, fLayout.fieldHasBuildId());
+        Long hasDebugLinkValue = event.getContent().getFieldValue(Long.class, fLayout.fieldHasDebugLink());
+        Long isPicValue = event.getContent().getFieldValue(Long.class, fLayout.fieldIsPic());
+
+        if (baddr == null ||
+                memsz == null ||
+                path == null ||
+                hasBuildIdValue == null ||
+                hasDebugLinkValue == null) {
+            LOGGER.warning(() -> "[UstDebugInfoStateProvider:InvalidDlOpenEvent] event=" + event.toString()); //$NON-NLS-1$
+            return;
+        }
 
-        /* "dlopen" events do not have a "is_pic" field, they always refer to PIC libs */
-        ITmfEventField isPicField = event.getContent().getField(fLayout.fieldIsPic());
-        Long isPicVal = (isPicField == null ? 1L : (Long) isPicField.getValue());
+        /*
+         * The is_pic field is only present in the lttng_ust_statedump:bin_info
+         * event. Binaries loaded with dlopen always have PIC. Therefore, we
+         * start assuming isPIC is true, and change our mind if the field is
+         * present and says the opposite.
+         */
+        boolean isPic = true;
+        if (isPicValue != null) {
+            isPic = (isPicValue != 0);
+        }
 
-        long endAddr = baddr.longValue() + memsz.longValue();
-        int addrQuark = ss.getQuarkAbsoluteAndAdd(vpid.toString(), baddr.toString());
+        boolean hasBuildId = hasBuildIdValue != 0;
+        boolean hasDebugLink = hasDebugLinkValue != 0;
 
         long ts = event.getTimestamp().getValue();
-        ss.modifyAttribute(ts, TmfStateValue.newValueLong(endAddr), addrQuark);
 
-        /*
-         * Add this library to the pending entries, the matching
-         * build_id/debug_link event will finish updating this attribute
-         */
-        BinInfo binInfo = new BinInfo(baddr, checkNotNull(sopath), isPicVal.intValue());
-        fPendingEntries.put(binInfo.fBaddr, binInfo);
+        PendingBinInfo p = new PendingBinInfo(hasBuildId, hasDebugLink, vpid, baddr, memsz, path, isPic);
+
+        processPendingBinInfo(p, ts, ss);
     }
 
     /**
@@ -241,37 +385,57 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
      *
      * Uses fields: Long baddr, long[] build_id
      */
-    private void handleBuildId(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) throws AttributeNotFoundException {
-        Long baddr = (Long) event.getContent().getField(fLayout.fieldBaddr()).getValue();
-        long[] buildIdArray = checkNotNull((long[]) event.getContent().getField(fLayout.fieldBuildId()).getValue());
+    private void handleBuildId(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) {
+        long[] buildIdArray = event.getContent().getFieldValue(long[].class, fLayout.fieldBuildId());
+        Long baddr = event.getContent().getFieldValue(Long.class, fLayout.fieldBaddr());
+
+        if (buildIdArray == null || baddr == null) {
+            LOGGER.warning(() -> "[UstDebugInfoStateProvider:InvalidBuildIdEvent] event=" + event.toString()); //$NON-NLS-1$
+            return;
+        }
+
         /*
          * Decode the buildID from the byte array in the trace field.
          * Use lower-case encoding, since this is how eu-readelf
          * displays it.
          */
-        String buildId = BaseEncoding.base16().encode(longArrayToByteArray(buildIdArray)).toLowerCase();
+        String buildId = checkNotNull(BaseEncoding.base16().encode(longArrayToByteArray(buildIdArray)).toLowerCase());
 
-        /* Retrieve the matching sopath from the pending entries */
-        BinInfo binInfo = fPendingEntries.remove(baddr);
-        if (binInfo == null) {
-            /*
-             * We did not previously handle the initial event for this
-             * library. Lost events?
-             */
-            Activator.getDefault().logWarning("UstDebugInfoStateProvider: Received a build_id event without a matching soinfo/dlopen one."); //$NON-NLS-1$
+        long ts = event.getTimestamp().getValue();
+
+        PendingBinInfo p = retrievePendingBinInfo(vpid, baddr);
+
+        /*
+         * We have never seen the bin_info event this event is related to,
+         * there's nothing much we can do.
+         */
+        if (p == null) {
+            return;
+        }
+
+        p.setBuildId(buildId);
+
+        processPendingBinInfo(p, ts, ss);
+    }
+
+    private void handleDebugLink(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) {
+        Long baddr = event.getContent().getFieldValue(Long.class, fLayout.fieldBaddr());
+        String debugLink = event.getContent().getFieldValue(String.class, fLayout.fieldDebugLinkFilename());
+
+        if (baddr == null || debugLink == null) {
+            LOGGER.warning(() -> "[UstDebugInfoStateProvider:InvalidDebugLinkEvent] event=" + event.toString()); //$NON-NLS-1$
             return;
         }
-        /* addrQuark should already exist */
-        int addrQuark = ss.getQuarkAbsolute(vpid.toString(), baddr.toString());
 
-        /* build-id attribute */
-        int buildIdQuark = ss.getQuarkRelativeAndAdd(addrQuark, buildId);
         long ts = event.getTimestamp().getValue();
-        ss.modifyAttribute(ts, TmfStateValue.newValueString(binInfo.fPath), buildIdQuark);
 
-        /* "is_pic" sub-attribute */
-        int isPicQuark = ss.getQuarkRelativeAndAdd(buildIdQuark, IS_PIC_ATTRIB);
-        ss.modifyAttribute(ts, TmfStateValue.newValueInt(binInfo.fIsPic), isPicQuark);
+        PendingBinInfo pendingBinInfo = retrievePendingBinInfo(vpid, baddr);
+        if (pendingBinInfo == null) {
+            return;
+        }
+
+        pendingBinInfo.setDebugLink(debugLink);
+        processPendingBinInfo(pendingBinInfo, ts, ss);
     }
 
     /**
@@ -280,7 +444,12 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
      * Uses fields: Long baddr
      */
     private void handleClose(ITmfEvent event, final Long vpid, final ITmfStateSystemBuilder ss) {
-        Long baddr = (Long) event.getContent().getField(fLayout.fieldBaddr()).getValue();
+        Long baddr = event.getContent().getFieldValue(Long.class, fLayout.fieldBaddr());
+
+        if (baddr == null) {
+            LOGGER.warning(() -> "[UstDebugInfoStateProvider:InvalidDlCloseEvent] event=" + event.toString()); //$NON-NLS-1$
+            return;
+        }
 
         try {
             int quark = ss.getQuarkAbsolute(vpid.toString(), baddr.toString());
@@ -321,5 +490,4 @@ public class UstDebugInfoStateProvider extends AbstractTmfStateProvider {
     public int getVersion() {
         return VERSION;
     }
-
 }
index 27ff9e0c6e9e695c0121a426f0d062d5860a2435..50074fe2c081096cd9839a432f7e32956aee2941 100644 (file)
@@ -86,10 +86,22 @@ public class LttngUst28EventLayout extends LttngUst27EventLayout {
         return "path";
     }
 
+    public String fieldHasBuildId() {
+        return "has_build_id";
+    }
+
+    public String fieldHasDebugLink() {
+        return "has_debug_link";
+    }
+
     public String fieldBuildId() {
         return "build_id";
     }
 
+    public String fieldDebugLinkFilename() {
+        return "filename";
+    }
+
     public String fieldIsPic() {
         return "is_pic";
     }
index db96a9e77156c97e00320d456d1d7917c4673450..1304764d71918dc4562a031c22faf788d55f5607 100644 (file)
@@ -9,6 +9,8 @@
 
 package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
 
+import org.eclipse.jdt.annotation.Nullable;
+
 /**
  * Object carrying the information about the "binary callsite" corresponding to
  * an instruction pointer. This consists in:
@@ -25,7 +27,7 @@ package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
 public class BinaryCallsite {
 
     private final String fBinaryFilePath;
-    private final String fBuildId;
+    private final @Nullable String fBuildId;
     private final long fOffset;
     private final boolean fIsPic;
 
@@ -49,7 +51,7 @@ public class BinaryCallsite {
      *            absolute address (if isPic is false), or if it is an offset in
      *            the binary (is isPic is true).
      */
-    public BinaryCallsite(String binaryFilePath, String buildId, long offset, boolean isPic) {
+    public BinaryCallsite(String binaryFilePath, @Nullable String buildId, long offset, boolean isPic) {
         if (offset < 0) {
             throw new IllegalArgumentException("Address offset cannot be negative"); //$NON-NLS-1$
         }
@@ -74,7 +76,7 @@ public class BinaryCallsite {
      *
      * @return The build-id
      */
-    public String getBuildId() {
+    public @Nullable String getBuildId() {
         return fBuildId;
     }
 
index 2fbe1aa2e78a8e7675624984f0d0156bf981d6e7..ca83c6ceb854ef99a5754beea2b12a508637d998 100644 (file)
@@ -14,15 +14,12 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.NavigableSet;
-import java.util.Optional;
+import java.util.OptionalLong;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.stream.Collectors;
 
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryFile;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
 import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoStateProvider;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
@@ -38,6 +35,7 @@ import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModul
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfUtils;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 
 /**
@@ -122,54 +120,56 @@ public class UstDebugInfoAnalysisModule extends TmfStateSystemAnalysisModule {
             return Collections.EMPTY_SET;
         }
 
-        Set<UstDebugInfoBinaryFile> files = new TreeSet<>();
+        final @NonNull Set<UstDebugInfoBinaryFile> files = new TreeSet<>();
         ImmutableList.Builder<Integer> builder = ImmutableList.builder();
-        List<Integer> vpidQuarks = ss.getSubAttributes(-1, false);
+        List<Integer> vpidQuarks = ss.getSubAttributes(ITmfStateSystem.ROOT_ATTRIBUTE, false);
         for (Integer vpidQuark : vpidQuarks) {
             builder.addAll(ss.getSubAttributes(vpidQuark, false));
         }
         List<Integer> baddrQuarks = builder.build();
 
-        /*
-         * For each "baddr" attribute, get the "buildId" sub-attribute,
-         * whose value is the file path.
-         */
-
-        for (Integer baddrQuark : baddrQuarks) {
-
-            List<Integer> buildIdQuarks = ss.getSubAttributes(baddrQuark, false);
-            for (Integer buildIdQuark : buildIdQuarks) {
-                String buildId = ss.getAttributeName(buildIdQuark);
+        try {
+            for (Integer baddrQuark : baddrQuarks) {
+                int buildIdQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.BUILD_ID_ATTRIB);
+                int debugLinkQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.DEBUG_LINK_ATTRIB);
+                int pathQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.PATH_ATTRIB);
+                int isPICQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
+                long ts = ss.getStartTime();
 
                 /*
-                 * Explore the history of this attribute "horizontally",
-                 * even though there should only be one valid interval.
+                 * Iterate over each mapping there ever was at this base
+                 * address.
                  */
-                ITmfStateInterval interval = StateSystemUtils.queryUntilNonNullValue(ss, buildIdQuark, ss.getStartTime(), Long.MAX_VALUE);
-                if (interval == null) {
-                    /*
-                     * If we created the attribute, we should have assigned
-                     * a value to it!
-                     */
-                    throw new IllegalStateException();
-                }
-                String filePath = interval.getStateValue().unboxStr();
+                ITmfStateInterval interval = StateSystemUtils.queryUntilNonNullValue(ss, baddrQuark, ts, Long.MAX_VALUE);
+                while (interval != null) {
+                    ts = interval.getStartTime();
+
+                    ITmfStateValue filePathStateValue = ss.querySingleState(ts, pathQuark).getStateValue();
+                    String filePath = filePathStateValue.unboxStr();
+
+                    ITmfStateValue buildIdStateValue = ss.querySingleState(ts, buildIdQuark).getStateValue();
+                    String buildId = unboxStrOrNull(buildIdStateValue);
 
-                /* Retrieve the value of "is_pic" at that time */
-                try {
-                    int isPicQuark = ss.getQuarkRelative(buildIdQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
-                    int isPicVal = ss.querySingleState(interval.getStartTime(), isPicQuark).getStateValue().unboxInt();
-                    boolean isPic = (isPicVal != 0);
+                    ITmfStateValue debuglinkStateValue = ss.querySingleState(ts, debugLinkQuark).getStateValue();
+                    String debugLink = unboxStrOrNull(debuglinkStateValue);
 
-                    files.add(new UstDebugInfoBinaryFile(filePath, buildId, isPic));
+                    ITmfStateValue isPICStateValue = ss.querySingleState(ts, isPICQuark).getStateValue();
+                    Boolean isPIC = isPICStateValue.unboxInt() != 0;
 
-                } catch (AttributeNotFoundException e) {
-                    /* We should have built "is_pic" sub-attributes */
-                    throw new IllegalStateException("Missing expected \"is_pic\" attribute"); //$NON-NLS-1$
-                } catch (StateSystemDisposedException e) {
-                    /* We're closing down, ignore */
+                    files.add(new UstDebugInfoBinaryFile(filePath, buildId, debugLink, isPIC));
+
+                    /*
+                     * Go one past the end of the interval, and perform the
+                     * query again to find the next mapping at this address.
+                     */
+                    ts = interval.getEndTime() + 1;
+                    interval = StateSystemUtils.queryUntilNonNullValue(ss, baddrQuark, ts, Long.MAX_VALUE);
                 }
             }
+        } catch (AttributeNotFoundException e) {
+            throw new IllegalStateException(e);
+        } catch (StateSystemDisposedException e) {
+            /* Oh well, such is life. */
         }
         return files;
     }
@@ -185,40 +185,49 @@ public class UstDebugInfoAnalysisModule extends TmfStateSystemAnalysisModule {
      * @param ip
      *            The instruction pointer of the trace event. Normally comes
      *            from a 'ip' context.
-     * @return The {@link UstDebugInfoBinaryFile} object, containing both the binary's path
-     *         and its build ID.
+     * @return A {@link UstDebugInfoLoadedBinaryFile} object, describing the
+     *         binary file and its base address.
+     * @noreference Meant to be used internally by
+     *              {@link UstDebugInfoBinaryAspect} only.
      */
-    @Nullable UstDebugInfoLoadedBinaryFile getMatchingFile(long ts, long vpid, long ip) {
-        waitForCompletion();
-        final ITmfStateSystem ss = getStateSystem();
-        if (ss == null) {
-            /* State system might not yet be initialized */
-            return null;
-        }
-
-        List<Integer> possibleBaddrQuarks = ss.getQuarks(String.valueOf(vpid), "*"); //$NON-NLS-1$
-
-        /* Get the most probable base address from all the known ones */
-        NavigableSet<Long> possibleBaddrs = possibleBaddrQuarks.stream()
-            .map(quark -> {
-                String baddrStr = ss.getAttributeName(quark.intValue());
-                return checkNotNull(Long.valueOf(baddrStr));
-            })
-            .collect(Collectors.toCollection(TreeSet::new));
+    @VisibleForTesting
+    public @Nullable UstDebugInfoLoadedBinaryFile getMatchingFile(long ts, long vpid, long ip) {
+        try {
+            waitForCompletion();
+            final ITmfStateSystem ss = getStateSystem();
+            if (ss == null) {
+                /* State system might not yet be initialized */
+                return null;
+            }
 
-        final Long potentialBaddr = possibleBaddrs.floor(ip);
-        if (potentialBaddr == null) {
-            return null;
-        }
+            List<Integer> possibleBaddrQuarks = ss.getQuarks(String.valueOf(vpid), "*"); //$NON-NLS-1$
+            List<ITmfStateInterval> state = ss.queryFullState(ts);
+
+            /* Get the most probable base address from all the known ones */
+            OptionalLong potentialBaddr = possibleBaddrQuarks.stream()
+                    .filter(quark -> {
+                        /* Keep only currently (at ts) mapped objects. */
+                        ITmfStateValue value = state.get(quark).getStateValue();
+                        return value.getType() == ITmfStateValue.Type.INTEGER && value.unboxInt() == 1;
+                    })
+                    .map(quark -> ss.getAttributeName(quark.intValue()))
+                    .mapToLong(baddrStr -> Long.parseLong(baddrStr))
+                    .filter(baddr -> baddr <= ip)
+                    .max();
+
+            if (!potentialBaddr.isPresent()) {
+                return null;
+            }
 
-        /* Make sure the 'ip' fits in the expected memory range */
-        try {
-            final List<ITmfStateInterval> fullState = ss.queryFullState(ts);
+            long baddr = potentialBaddr.getAsLong();
+            final int baddrQuark = ss.getQuarkAbsolute(String.valueOf(vpid),
+                                                       String.valueOf(baddr));
 
-            final int baddrQuark = ss.getQuarkAbsolute(String.valueOf(vpid), String.valueOf(potentialBaddr));
-            final long endAddr = fullState.get(baddrQuark).getStateValue().unboxLong();
+            final int memszQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.MEMSZ_ATTRIB);
+            final long memsz = state.get(memszQuark).getStateValue().unboxLong();
 
-            if (!(ip < endAddr)) {
+            /* Make sure the 'ip' fits the range of this object. */
+            if (!(ip < baddr + memsz)) {
                 /*
                  * Not the correct memory range after all. We do not have
                  * information about the library that was loaded here.
@@ -226,43 +235,32 @@ public class UstDebugInfoAnalysisModule extends TmfStateSystemAnalysisModule {
                 return null;
             }
 
-            /*
-             * We've found the correct base address, now to determine what
-             * library was loaded there at that time.
-             */
-            List<Integer> buildIds = ss.getSubAttributes(baddrQuark, false);
-            Optional<Integer> potentialBuildIdQuark = buildIds.stream()
-                .filter(id -> {
-                    int quark = id.intValue();
-                    ITmfStateValue value = fullState.get(quark).getStateValue();
-                    return (!value.isNull());
-                })
-                .findFirst();
-
-            if (!potentialBuildIdQuark.isPresent()) {
-                /* We didn't have the information after all. */
-                return null;
-            }
+            final int pathQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.PATH_ATTRIB);
+            String filePath = state.get(pathQuark).getStateValue().unboxStr();
 
-            /* Ok, we have everything we need! Return the information. */
-            long baddr = Long.parseLong(ss.getAttributeName(baddrQuark));
+            final int buildIdQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.BUILD_ID_ATTRIB);
+            ITmfStateValue buildIdValue = state.get(buildIdQuark).getStateValue();
+            String buildId = unboxStrOrNull(buildIdValue);
 
-            int buildIdQuark = potentialBuildIdQuark.get().intValue();
-            String buildId = ss.getAttributeName(buildIdQuark);
-            String filePath = fullState.get(buildIdQuark).getStateValue().unboxStr();
+            final int debugLinkQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.DEBUG_LINK_ATTRIB);
+            ITmfStateValue debugLinkValue = state.get(debugLinkQuark).getStateValue();
+            String debugLink = unboxStrOrNull(debugLinkValue);
 
-            int isPicQuark = ss.getQuarkRelative(buildIdQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
-            int isPicVal = fullState.get(isPicQuark).getStateValue().unboxInt();
-            boolean isPic = (isPicVal != 0);
+            final int isPicQuark = ss.getQuarkRelative(baddrQuark, UstDebugInfoStateProvider.IS_PIC_ATTRIB);
+            boolean isPic = state.get(isPicQuark).getStateValue().unboxInt() != 0;
 
-            return new UstDebugInfoLoadedBinaryFile(baddr, filePath, buildId, isPic);
+            return new UstDebugInfoLoadedBinaryFile(baddr, filePath, buildId, debugLink, isPic);
 
         } catch (AttributeNotFoundException e) {
+            // TODO: that's probably not true anymore
             /* We're only using quarks we've checked for. */
             throw new IllegalStateException(e);
         } catch (StateSystemDisposedException e) {
             return null;
         }
+    }
 
+    private static @Nullable String unboxStrOrNull(ITmfStateValue value) {
+        return (value.isNull() ? null : value.unboxStr());
     }
 }
index 8457b99af817a040c0a433c96558d5d94b3b70d4..15ce8c5b56e7e45ecdf56fc03cf3b6f2b625d6a6 100644 (file)
@@ -12,7 +12,6 @@ package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
 import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString;
 
 import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.internal.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
@@ -110,17 +109,15 @@ public class UstDebugInfoBinaryAspect implements ITmfEventAspect<BinaryCallsite>
 
         long offset;
         if (file.isPic()) {
-            offset = (ip - file.getBaseAddress());
+            offset = ip - file.getBaseAddress();
         } else {
             /*
-             * In the case of the object being non-position-independant (loaded
-             * at a very low address), we must pass the actual 'ip' address
-             * directly to addr2line.
+             * In the case of the object being non-position-independent, we
+             * must pass the actual 'ip' address directly to addr2line.
              */
             offset = ip;
         }
 
         return new BinaryCallsite(fullPath, file.getBuildId(), offset, file.isPic());
     }
-
 }
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java b/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoBinaryFile.java
new file mode 100644 (file)
index 0000000..b8556fd
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
+
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Wrapper class to reference to a particular binary, which can be an
+ * executable or library. It contains both the complete file path (at the
+ * time the trace was taken) and the build ID of the binary.
+ *
+ * @author Alexandre Montplaisir
+ * @noreference Meant to be used internally by the analysis only
+ */
+public class UstDebugInfoBinaryFile implements Comparable<UstDebugInfoBinaryFile> {
+
+    private final String fFilePath;
+    private final @Nullable String fBuildId;
+    private final @Nullable String fDebugLink;
+    private final boolean fIsPic;
+
+    /**
+     * Constructor
+     *
+     * @param filePath
+     *            The binary's path on the filesystem.
+     * @param buildId
+     *            The binary's unique buildID (in base16 form).
+     * @param debugLink
+     *            Path to the binary's separate debug info.
+     * @param isPic
+     *            Whether the code in the binary is position-independent.
+     */
+    public UstDebugInfoBinaryFile(String filePath, @Nullable String buildId,
+            @Nullable String debugLink, boolean isPic) {
+        fFilePath = filePath;
+        fBuildId = buildId;
+        fDebugLink = debugLink;
+        fIsPic = isPic;
+    }
+
+    /**
+     * Get the file's path, as was referenced to in the trace.
+     *
+     * @return The file path
+     */
+    public String getFilePath() {
+        return fFilePath;
+    }
+
+    /**
+     * Get the build ID of the binary. It should be a unique identifier.
+     *
+     * On Unix systems, you can use <pre>eu-readelf -n [binary]</pre> to get
+     * this ID.
+     *
+     * @return The file's build ID, or null if the file has no build ID..
+     */
+    public @Nullable String getBuildId() {
+        return fBuildId;
+    }
+
+    /**
+     * Get the path to the separate debug info of this binary.
+     *
+     * @return The path to the separate debug info, or null if the file has no
+     *         separate debug info.
+     */
+    public @Nullable String getDebugLink() {
+        return fDebugLink;
+    }
+
+    /**
+     * Return whether the given file (binary or library) is Position-Independent
+     * Code or not.
+     *
+     * This indicates whether the symbols in the ELF are absolute or relative to
+     * the runtime base address, and determines which address we need to pass to
+     * 'addr2line'.
+     *
+     * @return Whether this file is position-independent or not
+     */
+    public boolean isPic() {
+        return fIsPic;
+    }
+
+    @Override
+    public String toString() {
+        return com.google.common.base.Objects.toStringHelper(this)
+            .add("path", fFilePath)
+            .add("build_id", fBuildId)
+            .add("debug_link", fDebugLink)
+            .add("is_pic", fIsPic)
+            .toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(fFilePath, fBuildId, fDebugLink, fIsPic);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(getClass().equals(obj.getClass()))) {
+            return false;
+        }
+
+        UstDebugInfoBinaryFile other = (UstDebugInfoBinaryFile) obj;
+
+        return Objects.equals(fFilePath, other.fFilePath) &&
+                Objects.equals(fBuildId, other.fBuildId) &&
+                Objects.equals(fDebugLink, other.fDebugLink) &&
+                fIsPic == other.fIsPic;
+    }
+
+    /**
+     * Used for sorting. Sorts by using alphabetical order of the file
+     * paths.
+     */
+    @Override
+    public int compareTo(@Nullable UstDebugInfoBinaryFile o) {
+        if (o == null) {
+            return 1;
+        }
+        return fFilePath.compareTo(o.fFilePath);
+    }
+}
diff --git a/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java b/lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/lttng2/ust/core/analysis/debuginfo/UstDebugInfoLoadedBinaryFile.java
new file mode 100644 (file)
index 0000000..c4a3419
--- /dev/null
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo;
+
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Simple extension to {@link UstDebugInfoBinaryFile} that adds the base address at
+ * which the given binary or library is loaded.
+ *
+ * @author Alexandre Montplaisir
+ * @noreference Meant to be used internally by the analysis only
+ */
+public class UstDebugInfoLoadedBinaryFile extends UstDebugInfoBinaryFile {
+
+    private final long fBaseAddress;
+
+    /**
+     * Constructor
+     *
+     * @param baseAddress
+     *            The base address at which the binary or library is loaded
+     * @param filePath
+     *            The binary's path on the filesystem.
+     * @param buildId
+     *            The binary's unique buildID (in base16 form).
+     * @param debugLink
+     *            Path to the binary's separate debug info.
+     * @param isPic
+     *            Whether the code in the binary is position-independent.
+     */
+    public UstDebugInfoLoadedBinaryFile(long baseAddress, String filePath,
+            @Nullable String buildId, @Nullable String debugLink,
+            boolean isPic) {
+        super(filePath, buildId, debugLink, isPic);
+        this.fBaseAddress = baseAddress;
+    }
+
+    /**
+     * Return the base address at which the object is loaded.
+     *
+     * @return The base address
+     */
+    public long getBaseAddress() {
+        return fBaseAddress;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), fBaseAddress);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(getClass().equals(obj.getClass()))) {
+            return false;
+        }
+
+        if (!super.equals(obj)) {
+            return false;
+        }
+
+        UstDebugInfoLoadedBinaryFile other = (UstDebugInfoLoadedBinaryFile) obj;
+
+        return Objects.equals(fBaseAddress, other.fBaseAddress);
+    }
+}
This page took 0.045456 seconds and 5 git commands to generate.