diff --git a/libgomp/env.c b/libgomp/env.c
index 243c6267ef9..173c9271303 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -91,6 +91,8 @@ unsigned long gomp_places_list_len;
 uintptr_t gomp_def_allocator = omp_default_mem_alloc;
 int gomp_debug_var;
 int gompd_enabled;
+char *gompd_buffer;
+unsigned long gompd_env_buff_size;
 unsigned int gomp_num_teams_var;
 int gomp_nteams_var;
 int gomp_teams_thread_limit_var;
@@ -1453,6 +1455,187 @@ omp_display_env (int verbose)
 }
 ialias (omp_display_env)
 
+/* This function dumps all global ICVs into a buffer
+   in the form "icv-name=icv-value\n", so that OMPD can read the
+   buffer and display all icvs.  */
+
+static void
+dump_icvs (void)
+{
+  static char temp_buffer[500];
+  char temp_num_str[20];
+  strcat (temp_buffer, "OMP_DYNAMIC=");
+  strcat (temp_buffer, gomp_global_icv.dyn_var ? "TRUE\n" : "FALSE\n");
+  strcat (temp_buffer, "OMP_NESTED=");
+  strcat (temp_buffer,
+          gomp_global_icv.max_active_levels_var > 1 ? "TRUE\n" : "FALSE\n");
+  strcat (temp_buffer, "OMP_NUM_THREADS=");
+  sprintf (temp_num_str, "%lu\n", gomp_global_icv.nthreads_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_SCHEDULE=");
+  if ((gomp_global_icv.run_sched_var & GFS_MONOTONIC))
+    {
+      if (gomp_global_icv.run_sched_var != (GFS_MONOTONIC | GFS_STATIC))
+        strcat (temp_buffer, "MONOTONIC\n");
+    }
+  else if (gomp_global_icv.run_sched_var == GFS_STATIC)
+    strcat (temp_buffer, "NONMONOTONIC\n");
+  switch (gomp_global_icv.run_sched_var & ~GFS_MONOTONIC)
+    {
+    case GFS_RUNTIME:
+      strcat (temp_buffer, "RUNTIME");
+      if (gomp_global_icv.run_sched_chunk_size != 1)
+        {
+          sprintf (temp_num_str, ",%d", gomp_global_icv.run_sched_chunk_size);
+          strcat (temp_buffer, temp_num_str);
+        }
+      break;
+    case GFS_STATIC:
+      strcat (temp_buffer, "STATIC");
+      if (gomp_global_icv.run_sched_chunk_size != 0)
+        {
+          sprintf (temp_num_str, ",%d", gomp_global_icv.run_sched_chunk_size);
+          strcat (temp_buffer, temp_num_str);
+        }
+      break;
+    case GFS_DYNAMIC:
+      strcat (temp_buffer, "DYNAMIC");
+      if (gomp_global_icv.run_sched_chunk_size != 1)
+        {
+          sprintf (temp_num_str, ",%d", gomp_global_icv.run_sched_chunk_size);
+          strcat (temp_buffer, temp_num_str);
+        }
+      break;
+    case GFS_GUIDED:
+      strcat (temp_buffer, "GUIDED");
+      if (gomp_global_icv.run_sched_chunk_size != 1)
+        {
+          sprintf (temp_num_str, ",%d", gomp_global_icv.run_sched_chunk_size);
+          strcat (temp_buffer, temp_num_str);
+        }
+      break;
+    case GFS_AUTO:
+      strcat (temp_buffer, "AUTO");
+      break;
+    }
+  strcat (temp_buffer, "\n");
+
+  strcat (temp_buffer, "OMP_PROC_BIND=");
+  switch (gomp_global_icv.bind_var)
+    {
+    case omp_proc_bind_false:
+      strcat (temp_buffer, "FALSE");
+      break;
+    case omp_proc_bind_true:
+      strcat (temp_buffer, "TRUE");
+      break;
+    case omp_proc_bind_master:
+      strcat (temp_buffer, "MASTER"); /* TODO: Change to PRIMARY for OpenMP 5.1.  */
+      break;
+    case omp_proc_bind_close:
+      strcat (temp_buffer, "CLOSE");
+      break;
+    case omp_proc_bind_spread:
+      strcat (temp_buffer, "SPREAD");
+      break;
+    }
+  for (int i = 1; i < gomp_bind_var_list_len; i++)
+    switch (gomp_bind_var_list[i])
+      {
+      case omp_proc_bind_master:
+        strcat (temp_buffer, ",MASTER"); /* TODO: Change to PRIMARY for OpenMP 5.1. */
+        break;
+      case omp_proc_bind_close:
+        strcat (temp_buffer, ",CLOSE");
+        break;
+      case omp_proc_bind_spread:
+        strcat (temp_buffer, ",SPREAD");
+        break;
+      }
+  strcat (temp_buffer, "\n");
+
+  strcat (temp_buffer, "OMP_STACKSIZE=");
+  sprintf (temp_num_str, "%lu\n", stacksize);
+  strcat (temp_buffer, temp_num_str);
+
+  /* GOMP's default value is actually neither active nor passive.  */
+  strcat (temp_buffer, "OMP_WAIT_POLICY=");
+  strcat (temp_buffer, wait_policy > 0 ? "ACTIVE\n" : "PASSIVE\n");
+  strcat (temp_buffer, "OMP_THREAD_LIMIT=");
+  sprintf (temp_num_str, "%u\n", gomp_global_icv.thread_limit_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_MAX_ACTIVE_LEVELS=");
+  sprintf (temp_num_str, "%u\n", gomp_global_icv.max_active_levels_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_NUM_TEAMS=");
+  sprintf (temp_num_str, "%u\n", gomp_nteams_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_TEAMS_THREAD_LIMIT=");
+  sprintf (temp_num_str, "%u\n", gomp_teams_thread_limit_var);
+  strcat (temp_buffer, temp_num_str);
+
+  strcat (temp_buffer, "OMP_CANCELLATION=");
+  strcat (temp_buffer, gomp_cancel_var ? "TRUE\n" : "FALSE\n");
+  strcat (temp_buffer, "OMP_DEFAULT_DEVICE=");
+  sprintf (temp_num_str, "%d\n", gomp_global_icv.default_device_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_MAX_TASK_PRIORITY=");
+  sprintf (temp_num_str, "%d\n", gomp_max_task_priority_var);
+  strcat (temp_buffer, temp_num_str);
+  strcat (temp_buffer, "OMP_DISPLAY_AFFINITY=");
+  strcat (temp_buffer, gomp_display_affinity_var ? "TRUE\n" : "FALSE\n");
+  strcat (temp_buffer, "OMP_AFFINITY_FORMAT=");
+  strcat (temp_buffer, gomp_affinity_format_var);
+  strcat (temp_buffer, "\n");
+  strcat (temp_buffer, "OMP_ALLOCATOR=");
+  switch (gomp_def_allocator)
+    {
+#define C(v) case v: strcat (temp_buffer, #v); break;
+    C (omp_default_mem_alloc)
+    C (omp_large_cap_mem_alloc)
+    C (omp_const_mem_alloc)
+    C (omp_high_bw_mem_alloc)
+    C (omp_low_lat_mem_alloc)
+    C (omp_cgroup_mem_alloc)
+    C (omp_pteam_mem_alloc)
+    C (omp_thread_mem_alloc)
+#undef C
+    default: break;
+    }
+  strcat (temp_buffer, "\n");
+
+  strcat (temp_buffer, "OMP_TARGET_OFFLOAD=");
+  switch (gomp_target_offload_var)
+    {
+    case GOMP_TARGET_OFFLOAD_DEFAULT:
+      strcat (temp_buffer, "DEFAULT");
+      break;
+    case GOMP_TARGET_OFFLOAD_MANDATORY:
+      strcat (temp_buffer, "MANDATORY");
+      break;
+    case GOMP_TARGET_OFFLOAD_DISABLED:
+      strcat (temp_buffer, "DISABLED");
+      break;
+    }
+  strcat (temp_buffer, "\n");
+
+  strcat (temp_buffer, "GOMP_CPU_AFFINITY=\n");
+  strcat (temp_buffer, "GOMP_STACKSIZE=");
+  sprintf (temp_num_str, "%lu\n", stacksize);
+  strcat (temp_buffer, temp_num_str);
+#ifdef HAVE_INTTYPES_H
+  strcat (temp_buffer, "GOMP_SPINCOUNT=");
+  sprintf (temp_num_str, "%"PRIu64"\n", (uint64_t) gomp_spin_count_var);
+  strcat (temp_buffer, temp_num_str);
+#else
+  strcat (temp_buffer, "GOMP_SPINCOUNT=");
+  sprintf (temp_num_str, "%lu\n", (unsigned long) gomp_spin_count_var);
+  strcat (temp_buffer, temp_num_str);
+#endif
+  gompd_buffer = temp_buffer;
+  gompd_env_buff_size = (__UINT64_TYPE__) strlen (temp_buffer);
+}
+
 static void
 handle_omp_display_env (void)
 {
@@ -1519,7 +1702,10 @@ initialize_env (void)
   parse_int_secure ("GOMP_DEBUG", &gomp_debug_var, true);
   parse_debug ("OMP_DEBUG", &gompd_enabled);
   if (gompd_enabled == 1)
-    gompd_load ();
+    {
+      gompd_load ();
+      dump_icvs ();
+    }
 #ifndef HAVE_SYNC_BUILTINS
   gomp_mutex_init (&gomp_managed_threads_lock);
 #endif
diff --git a/libgomp/libgompd.map b/libgomp/libgompd.map
index 85bdc3695f6..439e5c313eb 100644
--- a/libgomp/libgompd.map
+++ b/libgomp/libgompd.map
@@ -16,6 +16,8 @@ OMPD_5.1 {
     ompd_thread_handle_compare;
     ompd_get_thread_id;
     ompd_get_device_from_thread;
+    ompd_get_display_control_vars;
+    ompd_rel_display_control_vars;
   local:
     *;
 };
diff --git a/libgomp/ompd-icv.c b/libgomp/ompd-icv.c
index 7f198d1638d..a0a2bec98dd 100644
--- a/libgomp/ompd-icv.c
+++ b/libgomp/ompd-icv.c
@@ -182,3 +182,76 @@ ompd_get_icv_string_from_scope (void *handle, ompd_scope_t scope,
     }
   return ompd_rc_error;
 }
+
+ompd_rc_t
+ompd_get_display_control_vars (ompd_address_space_handle_t *ah,
+                               const char *const **control_vars)
+{
+  CHECK (ah);
+  if (control_vars == NULL)
+    return ompd_rc_error;
+  /* GET the buffer size.  */
+  ompd_word_t buff_size = 0;
+  ompd_address_t symbol_addr = {OMPD_SEGMENT_UNSPECIFIED, 0};
+  ompd_rc_t ret;
+  GET_VALUE (ah->context, NULL, "gompd_env_buff_size", buff_size, buff_size,
+             target_sizes.sizeof_long, 1, ret, symbol_addr);
+  /* GET the buffer that has all environment variables.  */
+  ret = callbacks->symbol_addr_lookup (ah->context, NULL, "gompd_buffer",
+                                       &symbol_addr, NULL);
+  CHECK_RET (ret);
+  ompd_word_t addr = 0;
+  ret = callbacks->read_memory (ah->context, NULL, &symbol_addr,
+                                target_sizes.sizeof_pointer, &addr);
+  symbol_addr.address = addr;
+  char *env;
+  ret = callbacks->alloc_memory (buff_size, (void **) &env);
+  CHECK_RET (ret);
+  ret = callbacks->read_memory (ah->context, NULL, &symbol_addr,
+                                target_sizes.sizeof_char * buff_size,
+                                env);
+  CHECK_RET (ret);
+  ret = callbacks->device_to_host (ah->context, &env,
+                                   target_sizes.sizeof_char, buff_size, &env);
+  CHECK_RET (ret);
+  /* Count the number of variables.  */
+  int cntr = 1;  /* Take also the last NULL string.  */
+  for (int i = 0; i < buff_size; i++)
+    {
+      if (env[i] == '\n')
+        {
+          env[i] = '\0';
+          cntr++;
+        }
+    }
+  const char **temp_control_vars;
+  ret = callbacks->alloc_memory (cntr * sizeof (char *),
+                                 (void **) (&temp_control_vars));
+  CHECK_RET (ret);
+  char *idx = env;
+  temp_control_vars[0] = idx;
+  for (int i = 1; i < cntr - 1; i++)
+    {
+      while (*idx != '\0')
+        idx++;
+      if (idx > env + buff_size)
+        return ompd_rc_error;
+      temp_control_vars[i] = idx;
+    }
+  temp_control_vars[cntr - 1] = NULL;
+  *control_vars = temp_control_vars;
+  return ompd_rc_ok;
+}
+
+ompd_rc_t
+ompd_rel_display_control_vars (const char *const **control_vars)
+{
+  if (control_vars == NULL)
+    return ompd_rc_bad_input;
+  ompd_rc_t ret;
+  ret = callbacks->free_memory ((void *) control_vars[0]);
+  CHECK_RET (ret);
+  ret = callbacks->free_memory ((void *) control_vars);
+  CHECK_RET (ret);
+  return ompd_rc_ok;  
+}
