diff --git a/Makefile b/Makefile
index 9c91110466759f5eb47597511f8bf3d340c9addb..8bd4ad0cf6397d041cdf7844e9b2450d3b6c0c64 100644
--- a/Makefile
+++ b/Makefile
@@ -827,7 +827,7 @@ $(eval $(call include_generic_plugin_Makefile,$(PLUGIN_NAME)))
 PLUGIN_ENABLE:=$(ENABLE_EVA)
 PLUGIN_NAME:=Eva
 PLUGIN_DIR:=src/plugins/value
-PLUGIN_EXTRA_DIRS:=engine values domains domains/cvalue domains/apron \
+PLUGIN_EXTRA_DIRS:=engine values domains api domains/cvalue domains/apron \
 	domains/gauges domains/equality legacy partitioning utils gui_files \
 	values/numerors domains/numerors
 PLUGIN_TESTS_DIRS+=value/traces
@@ -910,11 +910,12 @@ PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode value_parameters \
 	partitioning/partitioning_index partitioning/trace_partitioning \
 	engine/mem_exec engine/iterator engine/initialization \
 	engine/compute_functions engine/analysis register \
+	api/general_requests \
 	utils/unit_tests \
 	$(APRON_CMO) $(NUMERORS_CMO)
 PLUGIN_CMI:= values/abstract_value values/abstract_location \
 	domains/abstract_domain domains/simpler_domains
-PLUGIN_DEPENDENCIES:=Callgraph LoopAnalysis RteGen
+PLUGIN_DEPENDENCIES:=Callgraph LoopAnalysis RteGen Server
 
 # These files are used by the GUI, but do not depend on Lablgtk
 VALUE_GUI_AUX:=gui_files/gui_types gui_files/gui_eval \
diff --git a/headers/header_spec.txt b/headers/header_spec.txt
index 0410e84facbd9940996a8d375593a164a05f0622..5d791ad40ee2ce6301155c602be4b5fb34761a11 100644
--- a/headers/header_spec.txt
+++ b/headers/header_spec.txt
@@ -1208,6 +1208,8 @@ src/plugins/value/Changelog_non_free: .ignore
 src/plugins/value/Eva.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/alarmset.ml: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/alarmset.mli: CEA_LGPL_OR_PROPRIETARY
+src/plugins/value/api/general_requests.ml: CEA_LGPL_OR_PROPRIETARY
+src/plugins/value/api/general_requests.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/domains/abstract_domain.mli: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/domains/printer_domain.ml: CEA_LGPL_OR_PROPRIETARY
 src/plugins/value/domains/printer_domain.mli: CEA_LGPL_OR_PROPRIETARY
diff --git a/ivette/api/kernel/ast/index.ts b/ivette/api/kernel/ast/index.ts
index a5bfaf9032e5e6800aa93703af31ab2e5d9bb0af..623884b14adfa9242c3387102ec72042534bad37 100644
--- a/ivette/api/kernel/ast/index.ts
+++ b/ivette/api/kernel/ast/index.ts
@@ -43,14 +43,14 @@ export const compute: Server.ExecRequest<null,null>= compute_internal;
 
 /** Marker kind */
 export enum markerKind {
-  /** Expression */
-  expression = 'expression',
-  /** Lvalue */
-  lvalue = 'lvalue',
   /** Variable */
   variable = 'variable',
   /** Function */
   function = 'function',
+  /** Expression */
+  expression = 'expression',
+  /** Lvalue */
+  lvalue = 'lvalue',
   /** Declaration */
   declaration = 'declaration',
   /** Statement */
diff --git a/ivette/api/plugins/eva/index.ts b/ivette/api/plugins/eva/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b46b34354923641cd17852220a4a7ff037b790f
--- /dev/null
+++ b/ivette/api/plugins/eva/index.ts
@@ -0,0 +1,40 @@
+/* --- Generated Frama-C Server API --- */
+
+/**
+   Eva General Services
+   @packageDocumentation
+   @module api/plugins/eva
+*/
+
+//@ts-ignore
+import * as Json from 'dome/data/json';
+//@ts-ignore
+import * as Compare from 'dome/data/compare';
+//@ts-ignore
+import * as Server from 'frama-c/server';
+//@ts-ignore
+import * as State from 'frama-c/states';
+
+
+const getCallers_internal: Server.GetRequest<
+  Json.key<'#fct'>,
+  [ Json.key<'#fct'>, Json.key<'#stmt'> ][]
+  > = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.eva.getCallers',
+  input:  Json.jKey<'#fct'>('#fct'),
+  output: Json.jList(Json.jTry(
+                       Json.jPair(
+                         Json.jFail(Json.jKey<'#fct'>('#fct'),
+                           '#fct expected'),
+                         Json.jFail(Json.jKey<'#stmt'>('#stmt'),
+                           '#stmt expected'),
+                       ))),
+};
+/** Get the list of call site of a function */
+export const getCallers: Server.GetRequest<
+  Json.key<'#fct'>,
+  [ Json.key<'#fct'>, Json.key<'#stmt'> ][]
+  >= getCallers_internal;
+
+/* ------------------------------------- */
diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts
index ea1737caee51e08a7610dc7560ffba30cf91c236..72dc636bbeb467e7d156457495eb61d94a8fba75 100644
--- a/ivette/src/frama-c/states.ts
+++ b/ivette/src/frama-c/states.ts
@@ -475,70 +475,227 @@ export interface FullLocation {
  *  but at least one of the two must be set.
  */
 export type Location = AtLeastOne<FullLocation>;
-export interface Selection {
 
-  /** Current selection. */
-  current?: Location;
+export interface HistorySelection {
   /** Previous locations with respect to the [[current]] one. */
   prevSelections: Location[];
   /** Next locations with respect to the [[current]] one. */
   nextSelections: Location[];
 }
 
+/** Actions on history selections:
+ * - `HISTORY_PREV` jumps to previous history location
+ *   (first in [[prevSelections]]).
+ * - `HISTORY_NEXT` jumps to next history location
+ *   (first in [[nextSelections]]).
+ */
+type HistorySelectActions = 'HISTORY_PREV' | 'HISTORY_NEXT';
+
+/** A selection of multiple locations. */
+export interface MultipleSelection {
+  /** The index of the current selected location in [[possibleSelections]]. */
+  index: number;
+  /** All locations forming a multiple selection. */
+  allSelections: Location[];
+}
+
+/** A select action on multiple locations. */
+export interface MultipleSelect {
+  readonly index: number;
+  readonly locations: Location[];
+}
+
+/** Select the [[index]]-nth location of the current multiple selection. */
+export interface NthSelect {
+  readonly index: number;
+}
+
+/** Actions on multiple selections:
+ * - [[MultipleSelect]].
+ * - [[NthSelect]].
+ * - `MULTIPLE_PREV` jumps to previous location of the multiple selections.
+ * - `MULTIPLE_NEXT` jumps to next location of the multiple selections.
+ */
+type MultipleSelectActions =
+  MultipleSelect | NthSelect
+  | 'MULTIPLE_PREV' | 'MULTIPLE_NEXT' | 'MULTIPLE_CLEAR';
+
+export interface Selection {
+  /** Current selection. May be one in [[history]] or [[multiple]]. */
+  current?: Location;
+  /** History of selections. */
+  history: HistorySelection;
+  /** Multiple selections at once. */
+  multiple: MultipleSelection;
+}
+
 /** A select action on a location. */
-export interface SelectAction {
+export interface SingleSelect {
   readonly location: Location;
 }
 
 /** Actions on selection:
- * - [[SelectAction]].
- * - `GO_BACK` jumps to previous location (first in [[prevSelections]]).
- * - `GO_FORWARD` jumps to next location (first in [[nextSelections]]).
+ * - [[SingleSelect]].
+ * - [[HistorySelectActions]].
+ * - [[MultipleSelectActions]].
  */
-export type SelectionActions = SelectAction | 'GO_BACK' | 'GO_FORWARD';
+export type SelectionActions =
+  SingleSelect | HistorySelectActions | MultipleSelectActions;
 
-function isSelect(a: SelectionActions): a is SelectAction {
-  return (a as SelectAction).location !== undefined;
+function isSingleSelect(a: SelectionActions): a is SingleSelect {
+  return (a as SingleSelect).location !== undefined;
 }
 
-/** Compute the next selection based on the current one and the given action. */
-function reducer(s: Selection, action: SelectionActions): Selection {
-  if (isSelect(action)) {
-    const [prevSelections, nextSelections] =
-      s.current && s.current.function !== action.location.function ?
-        [[s.current, ...s.prevSelections], []] :
-        [s.prevSelections, s.nextSelections];
-    return {
-      current: action.location,
-      prevSelections,
-      nextSelections,
-    };
-  }
-  const [pS, ...prevS] = s.prevSelections;
-  const [nS, ...nextS] = s.nextSelections;
+function isMultipleSelect(a: SelectionActions): a is MultipleSelect {
+  return (
+    (a as MultipleSelect).locations !== undefined &&
+    (a as MultipleSelect).index !== undefined
+  );
+}
+
+function isNthSelect(a: SelectionActions): a is NthSelect {
+  return (a as NthSelect).index !== undefined;
+}
+
+/** Update selection to the given location. */
+function selectLocation(s: Selection, location: Location): Selection {
+  const [prevSelections, nextSelections] =
+    s.current && s.current.function !== location.function ?
+      [[s.current, ...s.history.prevSelections], []] :
+      [s.history.prevSelections, s.history.nextSelections];
+  return {
+    ...s,
+    current: location,
+    history: { prevSelections, nextSelections },
+  };
+}
+
+/** Compute the next selection picking from the current history, depending on
+ *  action.
+ */
+function fromHistory(s: Selection, action: HistorySelectActions): Selection {
   switch (action) {
-    case 'GO_BACK':
+    case 'HISTORY_PREV': {
+      const [pS, ...prevS] = s.history.prevSelections;
       return {
+        ...s,
         current: pS,
-        prevSelections: prevS,
-        nextSelections: [(s.current as Location), ...s.nextSelections],
+        history: {
+          prevSelections: prevS,
+          nextSelections:
+            [(s.current as Location), ...s.history.nextSelections],
+        },
       };
-    case 'GO_FORWARD':
+    }
+    case 'HISTORY_NEXT': {
+      const [nS, ...nextS] = s.history.nextSelections;
       return {
+        ...s,
         current: nS,
-        prevSelections: [(s.current as Location), ...s.prevSelections],
-        nextSelections: nextS,
+        history: {
+          prevSelections:
+            [(s.current as Location), ...s.history.prevSelections],
+          nextSelections: nextS,
+        },
+      };
+    }
+    default:
+      return s;
+  }
+}
+
+/** Compute the next selection picking from the current multiple, depending on
+ *  action.
+ */
+function fromMultipleSelections(
+  s: Selection,
+  action: 'MULTIPLE_PREV' | 'MULTIPLE_NEXT' | 'MULTIPLE_CLEAR',
+): Selection {
+  switch (action) {
+    case 'MULTIPLE_PREV':
+    case 'MULTIPLE_NEXT': {
+      const index =
+        action === 'MULTIPLE_NEXT' ?
+          s.multiple.index + 1 :
+          s.multiple.index - 1;
+      if (0 <= index && index < s.multiple.allSelections.length) {
+        const multiple = { ...s.multiple, index };
+        return selectLocation(
+          { ...s, multiple },
+          s.multiple.allSelections[index],
+        );
+      }
+      return s;
+    }
+    case 'MULTIPLE_CLEAR':
+      return {
+        ...s,
+        multiple: {
+          index: 0,
+          allSelections: [],
+        },
       };
     default:
       return s;
   }
 }
 
-const GlobalSelection = new GlobalStates.State<Selection>({
+/** Compute the next selection based on the current one and the given action. */
+function reducer(s: Selection, action: SelectionActions): Selection {
+  if (isSingleSelect(action)) {
+    return selectLocation(s, action.location);
+  }
+  if (isMultipleSelect(action)) {
+    if (action.locations.length === 0)
+      return s;
+    const index = action.index > 0 ? action.index : 0;
+    const selection = selectLocation(s, action.locations[index]);
+    return {
+      ...selection,
+      multiple: {
+        allSelections: action.locations,
+        index,
+      },
+    };
+  }
+  if (isNthSelect(action)) {
+    const { index } = action;
+    if (0 <= index && index < s.multiple.allSelections.length) {
+      const location = s?.multiple.allSelections[index];
+      const selection = selectLocation(s, location);
+      const multiple = { ...selection.multiple, index };
+      return { ...selection, multiple };
+    }
+    return s;
+  }
+  switch (action) {
+    case 'HISTORY_PREV':
+    case 'HISTORY_NEXT':
+      return fromHistory(s, action);
+    case 'MULTIPLE_PREV':
+    case 'MULTIPLE_NEXT':
+    case 'MULTIPLE_CLEAR':
+      return fromMultipleSelections(s, action);
+    default:
+      return s;
+  }
+}
+
+/** The initial selection is empty. */
+const emptySelection = {
   current: undefined,
-  prevSelections: [],
-  nextSelections: [],
-});
+  history: {
+    prevSelections: [],
+    nextSelections: [],
+  },
+  multiple: {
+    index: 0,
+    allSelections: [],
+  },
+};
+
+const GlobalSelection = new GlobalStates.State<Selection>(emptySelection);
+Server.onShutdown(() => GlobalSelection.setValue(emptySelection));
 
 /**
    Current selection.
diff --git a/ivette/src/renderer/ASTview.tsx b/ivette/src/renderer/ASTview.tsx
index a635b1a7869202b426cbf363bf03a009a6194da9..ff2b3d97d473999cd9f6c85a31fdb1524f12ce16 100644
--- a/ivette/src/renderer/ASTview.tsx
+++ b/ivette/src/renderer/ASTview.tsx
@@ -3,6 +3,7 @@
 // --------------------------------------------------------------------------
 
 import React from 'react';
+import _ from 'lodash';
 import * as Server from 'frama-c/server';
 import * as States from 'frama-c/states';
 
@@ -14,6 +15,7 @@ import { IconButton } from 'dome/controls/buttons';
 import { Component, TitleBar } from 'frama-c/LabViews';
 
 import { printFunction, markerInfo } from 'api/kernel/ast';
+import { getCallers } from 'api/plugins/eva';
 
 import 'codemirror/mode/clike/clike';
 import 'codemirror/theme/ambiance.css';
@@ -56,14 +58,26 @@ async function loadAST(
         });
       } catch (err) {
         PP.error(
-          'Fail to retrieve the AST of function', theFunction,
-          'marker:', theMarker, err,
+          `Fail to retrieve the AST of function '${theFunction}' ` +
+          `and marker '${theMarker}':`, err,
         );
       }
     })();
   }
 }
 
+/** Compute the [[functionName]] caller locations. */
+async function functionCallers(functionName: string) {
+  try {
+    const data = await Server.send(getCallers, functionName);
+    const locations = data.map(([fct, marker]) => ({ function: fct, marker }));
+    return locations;
+  } catch (err) {
+    PP.error(`Fail to retrieve callers of function '${functionName}':`, err);
+    return [];
+  }
+}
+
 // --------------------------------------------------------------------------
 // --- AST Printer
 // --------------------------------------------------------------------------
@@ -72,12 +86,13 @@ const ASTview = () => {
 
   // Hooks
   const buffer = React.useMemo(() => new RichTextBuffer(), []);
-  const printed: React.MutableRefObject<string | undefined> = React.useRef();
+  const printed = React.useRef<string | undefined>();
   const [selection, updateSelection] = States.useSelection();
+  const multipleSelections = selection?.multiple.allSelections;
   const [theme, setTheme] = Dome.useGlobalSetting('ASTview.theme', 'default');
   const [fontSize, setFontSize] = Dome.useGlobalSetting('ASTview.fontSize', 12);
   const [wrapText, setWrapText] = Dome.useSwitch('ASTview.wrapText', false);
-  const markers = States.useSyncModel(markerInfo);
+  const markersInfo = States.useSyncArray(markerInfo);
 
   const theFunction = selection?.current?.function;
   const theMarker = selection?.current?.marker;
@@ -90,6 +105,15 @@ const ASTview = () => {
     }
   });
 
+  React.useEffect(() => {
+    const decorator = (marker: string) => {
+      if (multipleSelections?.some((location) => location?.marker === marker))
+        return 'highlighted-marker';
+      return undefined;
+    };
+    buffer.setDecorator(decorator);
+  }, [buffer, multipleSelections]);
+
   // Hook: marker scrolling
   React.useEffect(() => {
     if (theMarker) buffer.scroll(theMarker, undefined);
@@ -106,18 +130,45 @@ const ASTview = () => {
     }
   }
 
-  function onContextMenu(id: key<'#markerInfo'>) {
-    const marker = markers.getData(id);
-    if (marker && marker.kind === 'function') {
-      const item = {
-        label: `Go to definition of ${marker.name}`,
-        onClick: () => {
-          const location = { function: marker.name };
-          updateSelection({ location });
-        },
-      };
-      Dome.popupMenu([item]);
+  async function onContextMenu(id: key<'#markerInfo'>) {
+    const items = [];
+    const selectedMarkerInfo = markersInfo.find((e) => e.key === id);
+    switch (selectedMarkerInfo?.kind) {
+      case 'function': {
+        items.push({
+          label: `Go to definition of ${selectedMarkerInfo.name}`,
+          onClick: () => {
+            const location = { function: selectedMarkerInfo.name };
+            updateSelection({ location });
+          },
+        });
+        break;
+      }
+      case 'declaration': {
+        if (selectedMarkerInfo?.name) {
+          const locations = await functionCallers(selectedMarkerInfo.name);
+          const locationsByFunction = _.groupBy(locations, (e) => e.function);
+          _.forEach(locationsByFunction,
+            (e) => {
+              const callerName = e[0].function;
+              items.push({
+                label:
+                  `Go to caller ${callerName} ` +
+                  `${e.length > 1 ? `(${e.length} call sites)` : ''}`,
+                onClick: () => updateSelection({
+                  locations,
+                  index: locations.findIndex((l) => l.function === callerName),
+                }),
+              });
+            });
+        }
+        break;
+      }
+      default:
+        break;
     }
+    if (items.length > 0)
+      Dome.popupMenu(items);
   }
 
   // Theme Popup
diff --git a/ivette/src/renderer/Application.tsx b/ivette/src/renderer/Application.tsx
index 7aee4d0277d9d5bca6044a4e436c220f2006dcbd..a2d04f1270e603b9f71a4ed6d906a6e32560d109 100644
--- a/ivette/src/renderer/Application.tsx
+++ b/ivette/src/renderer/Application.tsx
@@ -20,29 +20,30 @@ import ASTview from './ASTview';
 import ASTinfo from './ASTinfo';
 import Globals from './Globals';
 import Properties from './Properties';
+import Locations from './Locations';
 
 // --------------------------------------------------------------------------
 // --- Selection Controls
 // --------------------------------------------------------------------------
 
-const SelectionControls = () => {
+const HistorySelectionControls = () => {
   const [selection, updateSelection] = States.useSelection();
 
-  const doPrevSelect = () => { updateSelection('GO_BACK'); };
-  const doNextSelect = () => { updateSelection('GO_FORWARD'); };
+  const doPrevSelect = () => { updateSelection('HISTORY_PREV'); };
+  const doNextSelect = () => { updateSelection('HISTORY_NEXT'); };
 
   return (
     <Toolbar.ButtonGroup>
       <Toolbar.Button
-        icon="MEDIA.PREV"
+        icon="ANGLE.LEFT"
         onClick={doPrevSelect}
-        disabled={!selection || selection.prevSelections.length === 0}
+        disabled={!selection || selection.history.prevSelections.length === 0}
         title="Previous location"
       />
       <Toolbar.Button
-        icon="MEDIA.NEXT"
+        icon="ANGLE.RIGHT"
         onClick={doNextSelect}
-        disabled={!selection || selection.nextSelections.length === 0}
+        disabled={!selection || selection.history.nextSelections.length === 0}
         title="Next location"
       />
     </Toolbar.ButtonGroup>
@@ -73,7 +74,7 @@ export default (() => {
           onClick={flipSidebar}
         />
         <Controller.Control />
-        <SelectionControls />
+        <HistorySelectionControls />
         <Toolbar.Filler />
         <Toolbar.Button
           icon="ITEMS.GRID"
@@ -99,6 +100,7 @@ export default (() => {
             <Properties />
             <ASTview />
             <ASTinfo />
+            <Locations />
           </Group>
         </LabView>
       </Splitter>
diff --git a/ivette/src/renderer/Controller.tsx b/ivette/src/renderer/Controller.tsx
index 699fa98dc8a2018dc87afac4848253179e67aaad..9a8b2c950ba6b64a685f62d0f15dfe41ff960dcc 100644
--- a/ivette/src/renderer/Controller.tsx
+++ b/ivette/src/renderer/Controller.tsx
@@ -257,13 +257,13 @@ const RenderConsole = () => {
           title="Discard changes"
         />
         <IconButton
-          icon="MEDIA.PREV"
+          icon="ANGLE.LEFT"
           display={edited}
           onClick={doPrev}
           title="Previous command"
         />
         <IconButton
-          icon="MEDIA.NEXT"
+          icon="ANGLE.RIGHT"
           display={edited}
           onClick={doNext}
           title="Next command"
diff --git a/ivette/src/renderer/Locations.tsx b/ivette/src/renderer/Locations.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3008d8d9cd2e83bd70089181f168d8f98578d9a2
--- /dev/null
+++ b/ivette/src/renderer/Locations.tsx
@@ -0,0 +1,130 @@
+// --------------------------------------------------------------------------
+// --- Table of (multiple) locations
+// --------------------------------------------------------------------------
+
+import React from 'react';
+import * as States from 'frama-c/states';
+
+import { CompactModel } from 'dome/table/arrays';
+import { Table, Column } from 'dome/table/views';
+import { Label } from 'dome/controls/labels';
+import { IconButton } from 'dome/controls/buttons';
+import { Space } from 'dome/frame/toolbars';
+import { Component, TitleBar } from 'frama-c/LabViews';
+
+// --------------------------------------------------------------------------
+// --- Locations Panel
+// --------------------------------------------------------------------------
+
+type LocationId = States.Location & { id: number };
+
+const LocationsTable = () => {
+
+  // Hooks
+  const [selection, updateSelection] = States.useSelection();
+  const model = React.useMemo(() => (
+    new CompactModel<number, LocationId>(({ id }: LocationId) => id)
+  ), []);
+  const multipleSelections = selection?.multiple;
+  const numberOfSelections = multipleSelections?.allSelections?.length;
+
+  // Updates [[model]] with the current multiple selections.
+  React.useEffect(() => {
+    if (numberOfSelections > 0) {
+      const data: LocationId[] =
+        multipleSelections.allSelections.map((d, i) => ({ ...d, id: i }));
+      model.replaceAllDataWith(data);
+    } else
+      model.clear();
+  }, [numberOfSelections, multipleSelections, model]);
+
+  // Callbacks
+  const onTableSelection = React.useCallback(
+    ({ id }) => updateSelection({ index: id }),
+    [updateSelection],
+  );
+
+  const reload = () => {
+    const location = multipleSelections.allSelections[multipleSelections.index];
+    updateSelection({ location });
+  };
+
+  // Component
+  return (
+    <>
+      <TitleBar>
+        <IconButton
+          icon="RELOAD"
+          onClick={reload}
+          enabled={numberOfSelections > 0}
+          title="Reload the current location"
+        />
+        <IconButton
+          icon="ANGLE.LEFT"
+          onClick={() => updateSelection('MULTIPLE_PREV')}
+          enabled={numberOfSelections > 1 && multipleSelections?.index > 0}
+          title="Previous location"
+        />
+        <IconButton
+          icon="ANGLE.RIGHT"
+          onClick={() => updateSelection('MULTIPLE_NEXT')}
+          enabled={
+            numberOfSelections > 1 &&
+            multipleSelections?.index < numberOfSelections - 1
+          }
+          title="Next location"
+        />
+        <Space />
+        <Label
+          className="component-info"
+          title={
+            `${numberOfSelections} selected ` +
+            `location${numberOfSelections > 1 ? 's' : ''}`
+          }
+        >
+          {multipleSelections?.allSelections.length === 0 ?
+            '0 / 0' :
+            `${multipleSelections?.index + 1} / ${numberOfSelections}`}
+        </Label>
+        <Space />
+        <IconButton
+          icon="TRASH"
+          onClick={() => updateSelection('MULTIPLE_CLEAR')}
+          enabled={numberOfSelections > 0}
+          title={`Clear location${numberOfSelections > 1 ? 's' : ''}`}
+        />
+      </TitleBar>
+      <Table
+        model={model}
+        selection={multipleSelections?.index}
+        onSelection={onTableSelection}
+      >
+        <Column
+          id="id"
+          label="#"
+          align="center"
+          width={25}
+          getter={(r: { id: number }) => r.id + 1}
+        />
+        <Column id="function" label="Function" width={120} />
+        <Column id="marker" label="Marker" fill />
+      </Table>
+    </>
+  );
+};
+
+// --------------------------------------------------------------------------
+// --- Export Component
+// --------------------------------------------------------------------------
+
+export default () => (
+  <Component
+    id="frama-c.locations"
+    label="Locations"
+    title="Browse multiple locations"
+  >
+    <LocationsTable />
+  </Component>
+);
+
+// --------------------------------------------------------------------------
diff --git a/ivette/src/renderer/style.css b/ivette/src/renderer/style.css
index 9a344e4e9e63f0b37f89ee513489e0a0661ad3b7..3d19a26bea7129623fdb9f80e4a788abf142f352 100644
--- a/ivette/src/renderer/style.css
+++ b/ivette/src/renderer/style.css
@@ -23,4 +23,8 @@
     text-overflow: ellipsis;
 }
 
+.highlighted-marker {
+    background-color: #FFFF66;
+}
+
 /* -------------------------------------------------------------------------- */
diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml
index 5a0b678ffbd832c6bede49520b1f1242d964b18c..3868f9d799dc6a5b0e15bb248aae35e4ec5705da 100644
--- a/src/plugins/server/kernel_ast.ml
+++ b/src/plugins/server/kernel_ast.ml
@@ -49,10 +49,10 @@ module MarkerKind = struct
   let kind name = Enum.tag ~name
       ~descr:(Md.plain (String.capitalize_ascii name)) kinds
 
+  let var  = kind "variable"
+  let fct  = kind "function"
   let expr = kind "expression"
   let lval = kind "lvalue"
-  let var = kind "variable"
-  let fct = kind "function"
   let decl = kind "declaration"
   let stmt = kind "statement"
   let glob = kind "global"
diff --git a/src/plugins/value/api/general_requests.ml b/src/plugins/value/api/general_requests.ml
new file mode 100644
index 0000000000000000000000000000000000000000..5c30a704fbcb1fc5e59c9b7bbcf611adc6091460
--- /dev/null
+++ b/src/plugins/value/api/general_requests.ml
@@ -0,0 +1,40 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2020                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Server
+
+let package = Package.package ~plugin:"eva"
+    ~title:"Eva General Services" ~readme:"eva.md" ()
+
+module CallSite = Data.Jpair (Kernel_ast.Kf) (Kernel_ast.Stmt)
+
+let callers kf =
+  let list = !Db.Value.callers kf in
+  List.concat (List.map (fun (kf, l) -> List.map (fun s -> kf, s) l) list)
+
+let () = Request.register ~package
+    ~kind:`GET ~name:"getCallers"
+    ~descr:(Markdown.plain "Get the list of call site of a function")
+    ~input:(module Kernel_ast.Kf) ~output:(module Data.Jlist (CallSite))
+    callers
+
+(**************************************************************************)
diff --git a/src/plugins/value/api/general_requests.mli b/src/plugins/value/api/general_requests.mli
new file mode 100644
index 0000000000000000000000000000000000000000..6568b925a92d2cd9bfb6896e3487b64f3736be10
--- /dev/null
+++ b/src/plugins/value/api/general_requests.mli
@@ -0,0 +1,23 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-2020                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** General Eva requests registered in the server. *)