*/
        struct {
                int fd;
+               void *obj_buf;
+               size_t obj_buf_sz;
                Elf *elf;
                GElf_Ehdr ehdr;
        } efile;
 };
 #define obj_elf_valid(o)       ((o)->efile.elf)
 
-static struct bpf_object *bpf_object__new(const char *path)
+static struct bpf_object *bpf_object__new(const char *path,
+                                         void *obj_buf,
+                                         size_t obj_buf_sz)
 {
        struct bpf_object *obj;
 
 
        strcpy(obj->path, path);
        obj->efile.fd = -1;
+
+       /*
+        * Caller of this function should also calls
+        * bpf_object__elf_finish() after data collection to return
+        * obj_buf to user. If not, we should duplicate the buffer to
+        * avoid user freeing them before elf finish.
+        */
+       obj->efile.obj_buf = obj_buf;
+       obj->efile.obj_buf_sz = obj_buf_sz;
+
        return obj;
 }
 
                obj->efile.elf = NULL;
        }
        zclose(obj->efile.fd);
+       obj->efile.obj_buf = NULL;
+       obj->efile.obj_buf_sz = 0;
 }
 
 static int bpf_object__elf_init(struct bpf_object *obj)
                return -EEXIST;
        }
 
-       obj->efile.fd = open(obj->path, O_RDONLY);
-       if (obj->efile.fd < 0) {
-               pr_warning("failed to open %s: %s\n", obj->path,
-                               strerror(errno));
-               return -errno;
+       if (obj->efile.obj_buf_sz > 0) {
+               /*
+                * obj_buf should have been validated by
+                * bpf_object__open_buffer().
+                */
+               obj->efile.elf = elf_memory(obj->efile.obj_buf,
+                                           obj->efile.obj_buf_sz);
+       } else {
+               obj->efile.fd = open(obj->path, O_RDONLY);
+               if (obj->efile.fd < 0) {
+                       pr_warning("failed to open %s: %s\n", obj->path,
+                                       strerror(errno));
+                       return -errno;
+               }
+
+               obj->efile.elf = elf_begin(obj->efile.fd,
+                               LIBBPF_ELF_C_READ_MMAP,
+                               NULL);
        }
 
-       obj->efile.elf = elf_begin(obj->efile.fd,
-                                LIBBPF_ELF_C_READ_MMAP,
-                                NULL);
        if (!obj->efile.elf) {
                pr_warning("failed to open %s as ELF file\n",
                                obj->path);
 }
 
 static struct bpf_object *
-__bpf_object__open(const char *path)
+__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
 {
        struct bpf_object *obj;
 
                return NULL;
        }
 
-       obj = bpf_object__new(path);
+       obj = bpf_object__new(path, obj_buf, obj_buf_sz);
        if (!obj)
                return NULL;
 
 
        pr_debug("loading %s\n", path);
 
-       return __bpf_object__open(path);
+       return __bpf_object__open(path, NULL, 0);
+}
+
+struct bpf_object *bpf_object__open_buffer(void *obj_buf,
+                                          size_t obj_buf_sz)
+{
+       /* param validation */
+       if (!obj_buf || obj_buf_sz <= 0)
+               return NULL;
+
+       pr_debug("loading object from buffer\n");
+
+       return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
 }
 
 void bpf_object__close(struct bpf_object *obj)