diff --git a/ivette/src/frama-c/kernel/ASTview.tsx b/ivette/src/frama-c/kernel/ASTview.tsx
index 19b1d4628518368367c9439abb0888a1edaf1bc9..e5f61224461ff97dda393a73bfdf3c5b98aff9b9 100644
--- a/ivette/src/frama-c/kernel/ASTview.tsx
+++ b/ivette/src/frama-c/kernel/ASTview.tsx
@@ -533,17 +533,21 @@ async function studia(props: StudiaProps): Promise<StudiaInfos> {
 // This field contains all the current function's callers, as inferred by Eva.
 const Callers = Editor.createField<Eva.CallSite[]>([]);
 
+// This field contains the function pointed to by the current hovered marker,
+// as inferred by Eva.
+const Callees = Editor.createField<Fct[]>([]);
+
 // This field contains information on markers.
 type GetMarkerData = (key: Ast.marker) => Ast.markerAttributesData | undefined;
 const GetMarkerData = Editor.createField<GetMarkerData>(() => undefined);
 
 const ContextMenuHandler = createContextMenuHandler();
 function createContextMenuHandler(): Editor.Extension {
-  const data = { tree: Tree, callers: Callers };
+  const data = { tree: Tree, callers: Callers, callees: Callees };
   const deps = { ...data, update: UpdateSelection, getData: GetMarkerData };
   return Editor.createEventHandler(deps, {
     contextmenu: (inputs, view, event) => {
-      const { tree, callers, update, getData } = inputs;
+      const { tree, callers, callees, update, getData } = inputs;
       const coords = { x: event.clientX, y: event.clientY };
       const position = view.posAtCoords(coords); if (!position) return;
       const node = coveringNode(tree, position);
@@ -572,6 +576,13 @@ function createContextMenuHandler(): Editor.Extension {
         const label = `Go to definition of ${attrs.name}`;
         items.push({ label, onClick });
       }
+      else if (attrs?.isFunctionPointer) {
+        Lodash.forEach(callees, (fct) => {
+          const onClick = (): void => update({ location: { fct } });
+          const label = `Go to definition of ${fct} (indirect)`;
+          items.push({ label, onClick });
+        });
+      }
       const enabled = attrs?.isLval;
       const onClick = (kind: access): void => {
         if (attrs && node.marker)
@@ -675,6 +686,11 @@ function useFctCallers(fct: Fct): Eva.CallSite[] {
   return States.useRequest(Eva.getCallers, fct) ?? [];
 }
 
+// Server request handler returning the given function's callers.
+function useCallees(marker: Marker): Fct[] {
+  return States.useRequest(Eva.getCallees, marker) ?? [];
+}
+
 // Server request handler returning the tainted lvalues.
 function useFctTaints(fct: Fct): Eva.LvalueTaints[] {
   return States.useRequest(Eva.taintedLvalues, fct, { onError: [] }) ?? [];
@@ -751,6 +767,10 @@ export default function ASTview(): JSX.Element {
   const taints = useFctTaints(fct);
   React.useEffect(() => TaintedLvalues.set(view, taints), [view, taints]);
 
+  // Retrieving data on currently hovered marker.
+  const callees = useCallees(hovered);
+  React.useEffect(() => Callees.set(view, callees), [view, callees]);
+
   return (
     <>
       <TitleBar>
diff --git a/ivette/src/frama-c/kernel/api/ast/index.ts b/ivette/src/frama-c/kernel/api/ast/index.ts
index e0b4ccbdead11fe6eacec4f4a7197d1c71bf1e5b..a02d403f09a8950ca65dd1ef150851b3eb60356a 100644
--- a/ivette/src/frama-c/kernel/api/ast/index.ts
+++ b/ivette/src/frama-c/kernel/api/ast/index.ts
@@ -147,6 +147,8 @@ export interface markerAttributesData {
   isLval: boolean;
   /** Whether it is a function symbol */
   isFunction: boolean;
+  /** Whether it is a function pointer */
+  isFunctionPointer: boolean;
   /** Whether it is a function declaration */
   isFunDecl: boolean;
   /** Function scope of the marker, if applicable */
@@ -165,6 +167,7 @@ export const jMarkerAttributesData: Json.Decoder<markerAttributesData> =
     descr: Json.jString,
     isLval: Json.jBoolean,
     isFunction: Json.jBoolean,
+    isFunctionPointer: Json.jBoolean,
     isFunDecl: Json.jBoolean,
     scope: Json.jOption(Json.jString),
     sloc: Json.jOption(jSource),
@@ -175,7 +178,8 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> =
   Compare.byFields
     <{ marker: marker, labelKind: string, titleKind: string, name: string,
        descr: string, isLval: boolean, isFunction: boolean,
-       isFunDecl: boolean, scope?: string, sloc?: source }>({
+       isFunctionPointer: boolean, isFunDecl: boolean, scope?: string,
+       sloc?: source }>({
     marker: byMarker,
     labelKind: Compare.alpha,
     titleKind: Compare.alpha,
@@ -183,6 +187,7 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> =
     descr: Compare.string,
     isLval: Compare.boolean,
     isFunction: Compare.boolean,
+    isFunctionPointer: Compare.boolean,
     isFunDecl: Compare.boolean,
     scope: Compare.defined(Compare.string),
     sloc: Compare.defined(bySource),
@@ -240,8 +245,8 @@ export const markerAttributes: State.Array<marker,markerAttributesData> = marker
 /** Default value for `markerAttributesData` */
 export const markerAttributesDataDefault: markerAttributesData =
   { marker: markerDefault, labelKind: '', titleKind: '', name: '', descr: '',
-    isLval: false, isFunction: false, isFunDecl: false, scope: undefined,
-    sloc: undefined };
+    isLval: false, isFunction: false, isFunctionPointer: false,
+    isFunDecl: false, scope: undefined, sloc: undefined };
 
 const getMainFunction_internal: Server.GetRequest<null,fct | undefined> = {
   kind: Server.RqKind.GET,
diff --git a/ivette/src/frama-c/plugins/eva/api/general/index.ts b/ivette/src/frama-c/plugins/eva/api/general/index.ts
index b5914a0f5c92d93d34d73efa8ad3201517c21811..18e0bc29ab498a0ad6855da61bf86fff71305bc2 100644
--- a/ivette/src/frama-c/plugins/eva/api/general/index.ts
+++ b/ivette/src/frama-c/plugins/eva/api/general/index.ts
@@ -135,6 +135,16 @@ const getCallers_internal: Server.GetRequest<fct,CallSite[]> = {
 /** Get the list of call site of a function */
 export const getCallers: Server.GetRequest<fct,CallSite[]>= getCallers_internal;
 
+const getCallees_internal: Server.GetRequest<marker,fct[]> = {
+  kind: Server.RqKind.GET,
+  name:   'plugins.eva.general.getCallees',
+  input:  jMarker,
+  output: Json.jArray(jFct),
+  signals: [],
+};
+/** Return the functions pointed to by a function pointer */
+export const getCallees: Server.GetRequest<marker,fct[]>= getCallees_internal;
+
 /** Data for array rows [`functions`](#functions)  */
 export interface functionsData {
   /** Entry identifier. */
diff --git a/src/plugins/eva/api/general_requests.ml b/src/plugins/eva/api/general_requests.ml
index 469c5cdbe61413fca9fe24cb5a40da8986f73826..cd68e1dc38623cdf42d756b002feeab6d2a1f8ba 100644
--- a/src/plugins/eva/api/general_requests.ml
+++ b/src/plugins/eva/api/general_requests.ml
@@ -86,6 +86,27 @@ let () = Request.register ~package
     ~input:(module Kernel_ast.Function) ~output:(module Data.Jlist (CallSite))
     callers
 
+let eval_callee stmt lval =
+  let expr = Eva_utils.lval_to_exp lval in
+  Results.(before stmt |> eval_callee expr |> default [])
+
+let callees = function
+  | Printer_tag.PLval (_kf, Kstmt stmt, (Mem _, NoOffset as lval))
+    when Cil.(isFunctionType (typeOfLval lval)) ->
+    eval_callee stmt lval
+  | Printer_tag.PLval (_kf, Kstmt stmt, lval)
+    when Cil.(isFunPtrType (Cil.typeOfLval lval)) ->
+    eval_callee stmt (Mem (Eva_utils.lval_to_exp lval), NoOffset)
+  | _ -> []
+
+let () = Request.register ~package
+    ~kind:`GET ~name:"getCallees"
+    ~descr:(Markdown.plain
+              "Return the functions pointed to by a function pointer")
+    ~input:(module Kernel_ast.Marker)
+    ~output:(module Data.Jlist (Kernel_ast.Function))
+    callees
+
 (* ----- Functions ---------------------------------------------------------- *)
 
 module Functions =
diff --git a/src/plugins/eva/api/values_request.ml b/src/plugins/eva/api/values_request.ml
index e6a33b7f6ad16d25b99b4fee80ba2de6447193c8..1e109a39629a2e95115db3b403be1112542972ba 100644
--- a/src/plugins/eva/api/values_request.ml
+++ b/src/plugins/eva/api/values_request.ml
@@ -115,7 +115,8 @@ let probe_property = function
   | _ -> raise Not_found
 
 let probe_marker = function
-  | Printer_tag.PLval (_, _, (Var vi, NoOffset))
+  | Printer_tag.PLval (_, _, lval)
+    when Cil.(isFunctionType (typeOfLval lval)) -> raise Not_found
   | PVDecl (_, _, vi) when Cil.isFunctionType vi.vtype -> raise Not_found
   | PLval (_, _, l) -> Plval l
   | PExp (_, _, e) -> Pexpr e
diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml
index 02fc76f1bc0aba538c3b951c7d44b4ac7fa4de13..f8c00bd913afce64be30134efa71558302ec8837 100644
--- a/src/plugins/server/kernel_ast.ml
+++ b/src/plugins/server/kernel_ast.ml
@@ -320,6 +320,13 @@ struct
     | Some vi -> Globals.Functions.mem vi
     | None -> false
 
+  let is_function_pointer = function
+    | PLval (_, _, (Mem _, NoOffset as lval))
+      when Cil.(isFunctionType (typeOfLval lval)) -> true
+    | PLval (_, _, lval)
+      when Cil.(isFunPtrType (Cil.typeOfLval lval)) -> true
+    | _ -> false
+
   let is_fundecl = function
     | PVDecl(Some _,Kglobal,vi) -> vi.vglob && Globals.Functions.mem vi
     | _ -> false
@@ -377,6 +384,14 @@ struct
       ~get:(fun (tag, _) -> is_function tag)
       model
 
+  let () =
+    States.column
+      ~name:"isFunctionPointer"
+      ~descr:(Md.plain "Whether it is a function pointer")
+      ~data:(module Jbool)
+      ~get:(fun (tag, _) -> is_function_pointer tag)
+      model
+
   let () =
     States.column
       ~name:"isFunDecl"