{"id":4868,"date":"2023-01-31T09:05:43","date_gmt":"2023-01-31T08:05:43","guid":{"rendered":"https:\/\/sanctuary.dev\/?p=4868"},"modified":"2023-02-09T09:41:29","modified_gmt":"2023-02-09T08:41:29","slug":"hypervisor-assisted-debugging","status":"publish","type":"post","link":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/","title":{"rendered":"Hypervisor-assisted Debugging"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"4868\" class=\"elementor elementor-4868\" data-elementor-post-type=\"post\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4009ec4 nd-elementor-section-full elementor-section-height-default elementor-section-height-default\" data-id=\"4009ec4\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1c06d8c\" data-id=\"1c06d8c\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-70defa4 elementor-widget elementor-widget-text-editor\" data-id=\"70defa4\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p class=\"nd-font-size-intro\">Working on a hypervisor has its own set of challenges. Among them, one of particular note is that of device emulation. This may be an exaggeration if you work in simulated environments such as ARM&#8217;s Fixed Virtual Platform. However, things can get out of hand once you switch to actual hardware.<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e0173ed nd-elementor-section-full elementor-section-height-default elementor-section-height-default\" data-id=\"e0173ed\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e21a2c8\" data-id=\"e21a2c8\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-32c916a elementor-widget elementor-widget-text-editor\" data-id=\"32c916a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<h2>Departure from Simulated Environments<\/h2>\n<p>A common component found on any embedded device is Power Management Integrated Circuit (PMIC) regulators. Their base function is relatively straightforward: managing the flow and direction of electrical power. They clamp input voltages\/currents and power on the available devices. But things are more complex. In truth, every manufacturer uses myriad different regulators with at least as many features heaped on top for good measure. E.g., a particular device driver may implement a subset of the power regulator driver&#8217;s features and probe it directly via <a href=\"https:\/\/elixir.bootlin.com\/linux\/v4.0\/source\/Documentation\/devicetree\/bindings\/mfd\/syscon.txt\">syscon<\/a> to ascertain the state of a related subsystem. That subsystem could be a frequency divider that needs to be active before resetting the device.<\/p>\n\n<h2>A Typical Problem with Power Regulators<\/h2>\n<p>All this becomes a problem when the integration with an SoC is too inflexible. Power regulators (or their drivers) need to be developed with virtualization in mind. Say, for example, that you want to partition devices between several VMs, each VM having exclusive access to its assigned device. Since on Arm architectures, device trees are used instead of mechanisms such as <a href=\"https:\/\/www.kernel.org\/doc\/html\/v5.2\/firmware-guide\/acpi\/enumeration.html\">ACPI Device Enumeration<\/a>, the first logical step is to delete the unrequired device nodes from each VM&#8217;s device tree. Said and done. But now you realize that while one VM&#8217;s driver has powered on its device, the second VM&#8217;s different driver has shut it back down. Why? Because that particular driver was expecting to find the first VM&#8217;s device node in the device tree and assumes that its absence indicates that the device was disabled. So why not make sure that its power supply is also disabled? As you can imagine, problems such as these take time to track down. Moreover, hardware debugging solutions are sometimes not an option due to lackluster support for specific platforms (usually, at least <a href=\"https:\/\/openocd.org\/\">OpenOCD<\/a> tends to have better interfacing with hardware debuggers than OEM software). And this brings us back to the topic at hand.<\/p>\n\n<h2>Advantages of Hypervisor-assisted Debugging<\/h2>\n<p>If you&#8217;re at a point where not even &#8216;printk&#8217; debugging is possible, your choices may seem limited. In fact, without a hardware debugger, the only option left is trapping the executing kernel into EL2 (hypervisor space), given that there is a hypervisor. This can be done in several ways:<\/p>\n\n<ul>\n \t<li><p><b>Trapping memory accesses<\/b> by not mapping the host physical address ranges to the guest physical address space. In essence, by using the Stage-2 Page Table feature in Arm processors (aka. Extended Page Tables &#8211; Intel, Nested Page Tables &#8211; AMD), we configure the MMU to perform two translations: one from guest virtual address space to guest physical address space, and another between the latter and host physical address space (i.e., the actual physical address). A failure during the first translation will be handled in EL1 (kernel space), but a failure during the second translation falls upon the hypervisor to resolve. This resolution involves performing the intended operation (according to the Exception Syndrome Register), incrementing the Program Counter, and returning to EL1. Between these steps, we can perform any debugging-related operation we desire.<\/p><\/li>\n \t<li><p><b>Inserting trap instructions<\/b>, which can be done either programmatically (like how software breakpoints work, i.e., replacing the first byte of the target instruction with an <code>int 3<\/code> or <code>brk<\/code> depending on the arch) or manually, by inserting <code>hvc<\/code> or <code>smc<\/code> instructions in the kernel code. The advantage over the previous method is that it allows more targeted debugging with less overhead.<\/p><\/li>\n \t<li><p><b>Hardware Debug Registers<\/b> more or less achieve the same effect as the first method. Still, depending on your requirements, these may be useful for implementing single stepping and limiting memory access traps to instruction fetches, thus significantly speeding up the process.<\/p><\/li>\n<\/ul>\nWhile these building blocks are available to do some rudimentary debugging, features such as VM Introspection and DWARF symbol parsing are not easy to integrate. Nonetheless, more sophisticated tools <b>are<\/b> required.\n\n<a href=\"https:\/\/github.com\/HyperDbg\/HyperDbg\">HyperDbg<\/a> is an example of a hypervisor-assisted debugger that uses Intel&#8217;s VT-x and TSX extensions to provide a more robust debugging infrastructure, similar to what would be needed in an Arm ecosystem. Nonetheless, research on this topic is nuanced by persisting challenges in reverse engineering and malware analysis. The improvement of portability and ease of use take a backseat when faced with state-of-the-art code packers and protectors.\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Debugging options are often quite restricted when porting low-level software to an embedded device. Serial output and printing do not work, so what&#8217;s next? In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.<\/p>\n","protected":false},"author":12,"featured_media":4893,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-4868","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-know-how"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Hypervisor-assisted Debugging - SANCTUARY<\/title>\n<meta name=\"description\" content=\"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Hypervisor-assisted Debugging - SANCTUARY\" \/>\n<meta property=\"og:description\" content=\"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\" \/>\n<meta property=\"og:site_name\" content=\"SANCTUARY\" \/>\n<meta property=\"article:published_time\" content=\"2023-01-31T08:05:43+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-02-09T08:41:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1280\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Patrick Jauernig\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@sanctuary_dev\" \/>\n<meta name=\"twitter:site\" content=\"@sanctuary_dev\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\"},\"author\":{\"name\":\"Patrick Jauernig\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/8a76acac1b46c49e9fb1948181536f5c\"},\"headline\":\"Hypervisor-assisted Debugging\",\"datePublished\":\"2023-01-31T08:05:43+00:00\",\"dateModified\":\"2023-02-09T08:41:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\"},\"wordCount\":758,\"publisher\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg\",\"articleSection\":[\"Know-how\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\",\"url\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\",\"name\":\"Hypervisor-assisted Debugging - SANCTUARY\",\"isPartOf\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg\",\"datePublished\":\"2023-01-31T08:05:43+00:00\",\"dateModified\":\"2023-02-09T08:41:29+00:00\",\"description\":\"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.\",\"breadcrumb\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage\",\"url\":\"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg\",\"contentUrl\":\"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg\",\"width\":1920,\"height\":1280,\"caption\":\"Hands resting on a laptop, coding.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/sanctuary.dev\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Hypervisor-assisted Debugging\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#website\",\"url\":\"https:\/\/sanctuary.dev\/en\/\",\"name\":\"SANCTUARY\",\"description\":\"The Embedded Security Experts\",\"publisher\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/sanctuary.dev\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#organization\",\"name\":\"SANCTUARY\",\"url\":\"https:\/\/sanctuary.dev\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/sanctuary.dev\/app\/uploads\/2022\/07\/sanctuary_linkedin_logo_v4.png\",\"contentUrl\":\"https:\/\/sanctuary.dev\/app\/uploads\/2022\/07\/sanctuary_linkedin_logo_v4.png\",\"width\":1841,\"height\":1841,\"caption\":\"SANCTUARY\"},\"image\":{\"@id\":\"https:\/\/sanctuary.dev\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/sanctuary_dev\",\"https:\/\/www.linkedin.com\/company\/sanctuary-dev\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/8a76acac1b46c49e9fb1948181536f5c\",\"name\":\"Patrick Jauernig\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f8d1d76523044ced2626b1c8c709acfeb177611c438a7965685bd8423af475b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f8d1d76523044ced2626b1c8c709acfeb177611c438a7965685bd8423af475b?s=96&d=mm&r=g\",\"caption\":\"Patrick Jauernig\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Hypervisor-assisted Debugging - SANCTUARY","description":"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/","og_locale":"en_US","og_type":"article","og_title":"Hypervisor-assisted Debugging - SANCTUARY","og_description":"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.","og_url":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/","og_site_name":"SANCTUARY","article_published_time":"2023-01-31T08:05:43+00:00","article_modified_time":"2023-02-09T08:41:29+00:00","og_image":[{"width":1920,"height":1280,"url":"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg","type":"image\/jpeg"}],"author":"Patrick Jauernig","twitter_card":"summary_large_image","twitter_creator":"@sanctuary_dev","twitter_site":"@sanctuary_dev","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#article","isPartOf":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/"},"author":{"name":"Patrick Jauernig","@id":"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/8a76acac1b46c49e9fb1948181536f5c"},"headline":"Hypervisor-assisted Debugging","datePublished":"2023-01-31T08:05:43+00:00","dateModified":"2023-02-09T08:41:29+00:00","mainEntityOfPage":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/"},"wordCount":758,"publisher":{"@id":"https:\/\/sanctuary.dev\/en\/#organization"},"image":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage"},"thumbnailUrl":"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg","articleSection":["Know-how"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/","url":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/","name":"Hypervisor-assisted Debugging - SANCTUARY","isPartOf":{"@id":"https:\/\/sanctuary.dev\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage"},"image":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage"},"thumbnailUrl":"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg","datePublished":"2023-01-31T08:05:43+00:00","dateModified":"2023-02-09T08:41:29+00:00","description":"In this blog post, we go through typical problems and hypervisor-assisted debugging as a potential alternative.","breadcrumb":{"@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#primaryimage","url":"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg","contentUrl":"https:\/\/sanctuary.dev\/app\/uploads\/2023\/02\/laptop_coding.jpg","width":1920,"height":1280,"caption":"Hands resting on a laptop, coding."},{"@type":"BreadcrumbList","@id":"https:\/\/sanctuary.dev\/en\/blog\/hypervisor-assisted-debugging\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sanctuary.dev\/en\/"},{"@type":"ListItem","position":2,"name":"Hypervisor-assisted Debugging"}]},{"@type":"WebSite","@id":"https:\/\/sanctuary.dev\/en\/#website","url":"https:\/\/sanctuary.dev\/en\/","name":"SANCTUARY","description":"The Embedded Security Experts","publisher":{"@id":"https:\/\/sanctuary.dev\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sanctuary.dev\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/sanctuary.dev\/en\/#organization","name":"SANCTUARY","url":"https:\/\/sanctuary.dev\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sanctuary.dev\/en\/#\/schema\/logo\/image\/","url":"https:\/\/sanctuary.dev\/app\/uploads\/2022\/07\/sanctuary_linkedin_logo_v4.png","contentUrl":"https:\/\/sanctuary.dev\/app\/uploads\/2022\/07\/sanctuary_linkedin_logo_v4.png","width":1841,"height":1841,"caption":"SANCTUARY"},"image":{"@id":"https:\/\/sanctuary.dev\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/sanctuary_dev","https:\/\/www.linkedin.com\/company\/sanctuary-dev\/"]},{"@type":"Person","@id":"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/8a76acac1b46c49e9fb1948181536f5c","name":"Patrick Jauernig","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sanctuary.dev\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f8d1d76523044ced2626b1c8c709acfeb177611c438a7965685bd8423af475b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f8d1d76523044ced2626b1c8c709acfeb177611c438a7965685bd8423af475b?s=96&d=mm&r=g","caption":"Patrick Jauernig"}}]}},"_links":{"self":[{"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/posts\/4868","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/comments?post=4868"}],"version-history":[{"count":24,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/posts\/4868\/revisions"}],"predecessor-version":[{"id":4912,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/posts\/4868\/revisions\/4912"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/media\/4893"}],"wp:attachment":[{"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/media?parent=4868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/categories?post=4868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sanctuary.dev\/en\/wp-json\/wp\/v2\/tags?post=4868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}