SKEL_BLACKLIST := btf__% test_pinning_invalid.c test_sk_assign.c
 
-LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h linked_vars.skel.h
+LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h          \
+               linked_vars.skel.h linked_maps.skel.h
 
 test_static_linked.skel.h-deps := test_static_linked1.o test_static_linked2.o
 linked_funcs.skel.h-deps := linked_funcs1.o linked_funcs2.o
 linked_vars.skel.h-deps := linked_vars1.o linked_vars2.o
+linked_maps.skel.h-deps := linked_maps1.o linked_maps2.o
 
 LINKED_BPF_SRCS := $(patsubst %.o,%.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps)))
 
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Facebook */
+
+#include <test_progs.h>
+#include <sys/syscall.h>
+#include "linked_maps.skel.h"
+
+void test_linked_maps(void)
+{
+       int err;
+       struct linked_maps *skel;
+
+       skel = linked_maps__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "skel_open"))
+               return;
+
+       err = linked_maps__attach(skel);
+       if (!ASSERT_OK(err, "skel_attach"))
+               goto cleanup;
+
+       /* trigger */
+       syscall(SYS_getpgid);
+
+       ASSERT_EQ(skel->bss->output_first1, 2000, "output_first1");
+       ASSERT_EQ(skel->bss->output_second1, 2, "output_second1");
+       ASSERT_EQ(skel->bss->output_weak1, 2, "output_weak1");
+
+cleanup:
+       linked_maps__destroy(skel);
+}
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Facebook */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+struct my_key { long x; };
+struct my_value { long x; };
+
+struct {
+       __uint(type, BPF_MAP_TYPE_HASH);
+       __type(key, struct my_key);
+       __type(value, struct my_value);
+       __uint(max_entries, 16);
+} map1 SEC(".maps");
+
+ /* Matches map2 definition in linked_maps2.c. Order of the attributes doesn't
+  * matter.
+  */
+typedef struct {
+       __uint(max_entries, 8);
+       __type(key, int);
+       __type(value, int);
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+} map2_t;
+
+extern map2_t map2 SEC(".maps");
+
+/* This should be the winning map definition, but we have no way of verifying,
+ * so we just make sure that it links and works without errors
+ */
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __type(key, int);
+       __type(value, int);
+       __uint(max_entries, 16);
+} map_weak __weak SEC(".maps");
+
+int output_first1;
+int output_second1;
+int output_weak1;
+
+SEC("raw_tp/sys_enter")
+int BPF_PROG(handler_enter1)
+{
+       /* update values with key = 1 */
+       int key = 1, val = 1;
+       struct my_key key_struct = { .x = 1 };
+       struct my_value val_struct = { .x = 1000 };
+
+       bpf_map_update_elem(&map1, &key_struct, &val_struct, 0);
+       bpf_map_update_elem(&map2, &key, &val, 0);
+       bpf_map_update_elem(&map_weak, &key, &val, 0);
+
+       return 0;
+}
+
+SEC("raw_tp/sys_exit")
+int BPF_PROG(handler_exit1)
+{
+       /* lookup values with key = 2, set in another file */
+       int key = 2, *val;
+       struct my_key key_struct = { .x = 2 };
+       struct my_value *value_struct;
+
+       value_struct = bpf_map_lookup_elem(&map1, &key_struct);
+       if (value_struct)
+               output_first1 = value_struct->x;
+
+       val = bpf_map_lookup_elem(&map2, &key);
+       if (val)
+               output_second1 = *val;
+
+       val = bpf_map_lookup_elem(&map_weak, &key);
+       if (val)
+               output_weak1 = *val;
+       
+       return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Facebook */
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+/* modifiers and typedefs are ignored when comparing key/value types */
+typedef struct my_key { long x; } key_type;
+typedef struct my_value { long x; } value_type;
+
+extern struct {
+       __uint(max_entries, 16);
+       __type(key, key_type);
+       __type(value, value_type);
+       __uint(type, BPF_MAP_TYPE_HASH);
+} map1 SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __type(key, int);
+       __type(value, int);
+       __uint(max_entries, 8);
+} map2 SEC(".maps");
+
+/* this definition will lose, but it has to exactly match the winner */
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __type(key, int);
+       __type(value, int);
+       __uint(max_entries, 16);
+} map_weak __weak SEC(".maps");
+
+int output_first2;
+int output_second2;
+int output_weak2;
+
+SEC("raw_tp/sys_enter")
+int BPF_PROG(handler_enter2)
+{
+       /* update values with key = 2 */
+       int key = 2, val = 2;
+       key_type key_struct = { .x = 2 };
+       value_type val_struct = { .x = 2000 };
+
+       bpf_map_update_elem(&map1, &key_struct, &val_struct, 0);
+       bpf_map_update_elem(&map2, &key, &val, 0);
+       bpf_map_update_elem(&map_weak, &key, &val, 0);
+
+       return 0;
+}
+
+SEC("raw_tp/sys_exit")
+int BPF_PROG(handler_exit2)
+{
+       /* lookup values with key = 1, set in another file */
+       int key = 1, *val;
+       key_type key_struct = { .x = 1 };
+       value_type *value_struct;
+
+       value_struct = bpf_map_lookup_elem(&map1, &key_struct);
+       if (value_struct)
+               output_first2 = value_struct->x;
+
+       val = bpf_map_lookup_elem(&map2, &key);
+       if (val)
+               output_second2 = *val;
+
+       val = bpf_map_lookup_elem(&map_weak, &key);
+       if (val)
+               output_weak2 = *val;
+
+       return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";